En una base de datos de Cloud Spanner, este crea un índice de forma automática para la clave primaria de cada tabla. Por ejemplo, no es necesario realizar ninguna acción para indexar la clave primaria de Singers
, ya que se indexa de forma automática.
También puedes crear índices secundarios para otras columnas. Agregar un índice secundario a una columna hace que la búsqueda de datos en esa columna sea más eficiente. Por ejemplo, si necesitas buscar con rapidez un conjunto de valores SingerId
para un rango determinado de valores LastName
, deberías crear un índice secundario en LastName
, así Cloud Spanner no necesita analizar toda la tabla.
Si la búsqueda del ejemplo anterior se realiza dentro de una transacción de lectura y escritura, la búsqueda más eficiente también evita que se mantengan bloqueos en toda la tabla, lo que permite inserciones y actualizaciones simultáneas en la tabla para filas fuera del rango de búsqueda LastName
.
Cloud Spanner almacena los siguientes datos en cada índice secundario:
- Todas las columnas de clave de la tabla base
- Todas las columnas que se incluyen en el índice
- Todas las columnas especificadas en la cláusula
STORING
opcional de la definición del índice
Con el tiempo, Cloud Spanner analiza tus tablas con el fin de asegurarse de que tus índices secundarios se usen para las consultas adecuadas.
Agrega un índice secundario
El momento más eficaz para agregar un índice secundario es cuando creas la tabla. Si deseas crear una tabla y sus índices al mismo tiempo, envía a Cloud Spanner las instrucciones DDL para la tabla nueva y los nuevos índices en una sola solicitud.
En Cloud Spanner, también puedes agregar un nuevo índice secundario a una tabla existente mientras la base de datos continúa entregando tráfico. Al igual que cualquier otro cambio de esquema en Cloud Spanner, agregar un índice a una base de datos existente no requiere que la base de datos esté sin conexión ni bloquea columnas o tablas completas.
Cada vez que se agrega un índice nuevo a una tabla existente, Cloud Spanner reabastece o propaga de forma automática el índice para reflejar una vista actualizada de los datos que se indexan. Cloud Spanner administra este proceso de reabastecimiento por ti y usa recursos adicionales durante el reabastecimiento de los índices.
La creación del índice puede tardar desde varios minutos hasta muchas horas. Debido a que la creación de índices es una actualización de esquema, está sujeta a las mismas restricciones de rendimiento que cualquier otra actualización de esquema. El tiempo necesario para crear un índice secundario depende de varios factores:
- El tamaño del conjunto de datos
- La cantidad de nodos en la instancia
- La carga de la instancia
Para ver el progreso de un proceso de reabastecimiento de índice, consulta la sección de progreso.
Ten en cuenta que usar la columna confirmar marca de tiempo como la primera parte del índice secundario puede crear hotspots y reducir el rendimiento de la operación de escritura.
Usa la declaración CREATE INDEX
para definir un índice secundario en tu esquema. Estos son algunos ejemplos:
Para indexar todos los Singers
en la base de datos por su nombre y apellido, ejecuta el comando siguiente:
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName)
Para crear un índice de todas las Songs
en la base de datos por el valor de SongName
, ejecuta el comando siguiente:
CREATE INDEX SongsBySongName ON Songs(SongName)
Si deseas indexar solo las canciones de un cantante en particular, usa la cláusula INTERLEAVE IN
para intercalar el índice en la tabla Singers
:
CREATE INDEX SongsBySingerSongName ON Songs(SingerId, SongName),
INTERLEAVE IN Singers
Para indexar solo las canciones de un álbum en particular, ejecuta lo siguiente:
CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName),
INTERLEAVE IN Albums
Para indexar por orden descendente de SongName
, ejecuta lo siguiente:
CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC),
INTERLEAVE IN Albums
Ten en cuenta que la anotación DESC
anterior solo se aplica a SongName
. Para indexarlos por orden descendente de otras claves de índice, anótalas con DESC
y SingerId DESC, AlbumId DESC
.
También ten en cuenta que PRIMARY_KEY
es una palabra reservada y no se puede usar como el nombre de un índice. Es el nombre asignado al seudo-índice que se crea cuando se crea una tabla con especificaciones de CLAVE PRIMARIA
Para obtener más detalles y prácticas recomendadas sobre cómo elegir índices no intercalados e índices intercalados, consulta Opciones de índice y Usa un índice intercalado en una columna cuyo valor aumenta o disminuye de forma monotónica.
Visualiza el progreso del reabastecimiento de índices
Pasos para ver el progreso del reabastecimiento de índices
Un proceso de reabastecimiento de índice es parte de una operación de larga duración de esquema-actualización, ya que la adición de un índice secundario requiere una actualización del esquema. Puedes ver el progreso del reabastecimiento de índice mediante el ID de operación. Si no tienes el ID de la operación, puedes encontrarlo con gcloud spanner operations list:
gcloud spanner operations list --instance=INSTANCE --database=DATABASE
Notas de uso:
Para limitar la lista de operaciones que muestra este comando, especifica la marca
--filter
. Por ejemplo, usa el siguiente filtro para mostrar las operaciones de actualización de esquema.--filter="@TYPE:UpdateDatabaseDdlMetadata"
Si deseas obtener información sobre la sintaxis de filtros, consulta gcloud topic filters. Para obtener más información sobre cómo filtrar operaciones de la base de datos, consulta el campo
filter
en ListDatabaseOperationsRequest.
Este es un ejemplo del resultado:
OPERATION_ID STATEMENTS DONE @TYPE _auto_op_123456 CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName) False UpdateDatabaseDdlMetadata CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName), INTERLEAVE IN Albums _auto_op_234567 True CreateDatabaseMetadata
Para realizar el seguimiento del progreso de uno o más procesos de reabastecimiento de índice secundario, usa gcloud spanner operations describe:
gcloud spanner operations describe _auto_op_123456 \ --instance=INSTANCE \ --database=DATABASE
Aquí hay un ejemplo del resultado de una operación de larga duración de actualización de esquema que contiene dos procesos de reabastecimiento de índice:
done: true metadata: '@type': type.googleapis.com/google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata commitTimestamps: - '2021-01-22T21:58:42.912540Z' database: projects/my-project/instances/test-instance/databases/example-db progress: - endTime: '2021-01-22T21:58:42.912540Z' progressPercent: 100 startTime: '2021-01-22T21:58:11.053996Z' - progressPercent: 67 startTime: '2021-01-22T21:58:11.053996Z' statements: - CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName) - CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName), INTERLEAVE IN Albums name: projects/my-project/instances/test-instance/databases/example-db/operations/_auto_op_123456 response: '@type': type.googleapis.com/google.protobuf.Empty
El progreso de cada declaración de reabastecimiento de índice se puede encontrar en el campo
progress
. Para cada declaración en el arreglo de instrucción, hay un campo correspondiente en el arreglo de progreso. Y los camposstartTime
yendTime
se propagan cuando están disponibles. El orden de la matriz de progreso corresponde al orden del arreglo de declaraciones.
Situaciones cuando se visualiza el progreso del reabastecimiento de índice
Hay diferentes situaciones con las que un usuario podría enfrentar cuando intenta verificar el progreso de un reabastecimiento de índice. Las declaraciones de creación de índices que requieren un reabastecimiento de índice son parte de las operaciones de actualización de esquema y pueden haber varias declaraciones que forman parte de una operación de actualización del esquema.
La primera situación es la más simple, que es cuando la declaración de creación de índices es la primera declaración de la operación de actualización del esquema. El campo startTime
para la declaración de creación de índices se propagará con el tiempo de inicio de la operación de actualización del esquema, ya que es la primera declaración y será la primera que se procesará y ejecutará debido a al orden de ejecución.
El campo progressPercent
de la declaración de creación de índices se propagará cuando el progreso del reabastecimiento de índices supere el 0%. El campo endTime
se propaga una vez que se confirma la declaración.
La segunda situación es cuando la declaración de creación de índices no es la primera declaración de la operación de actualización de esquema. Ningún campo relacionado con la declaración de creación de índices se propagará hasta que las declaraciones anteriores se hayan confirmado debido al orden de ejecución.
Una vez que se hayan confirmado las declaraciones anteriores, el startTime
del campo de progreso de la declaración de creación de índices será el primer atributo propagado. Luego, el campo progressPercent
de la declaración de creación de índices se propagará cuando el progreso del reabastecimiento de índices supere el 0%. El campo endTime
se propaga una vez que se confirma la declaración.
Cancela la creación del índice
Puedes usar el SDK de Cloud para cancelar la creación del índice. Si deseas recuperar una lista de operaciones de actualización de esquema para una base de datos de Cloud Spanner, usa el comando gcloud spanner operations list
y, luego, incluye la opción --filter
:
gcloud spanner operations list \
--instance=INSTANCE \
--database=DATABASE \
--filter="@TYPE:UpdateDatabaseDdlMetadata"
Busca el OPERATION_ID
de la operación que deseas cancelar y, luego, usa el comando gcloud spanner operations cancel
con el fin de cancelarla:
gcloud spanner operations cancel OPERATION_ID \
--instance=INSTANCE \
--database=DATABASE
Visualiza los índices existentes
Para ver información sobre los índices existentes en una base de datos, puedes usar Google Cloud Console o la herramienta de línea de comandos de gcloud
:
Console
Ve a la página Instancias de Cloud Spanner en Cloud Console.
Haz clic en el nombre de la instancia que deseas ver.
En el panel izquierdo, haz clic en la base de datos que desea ver y, luego, en la tabla que deseas visualizar.
Haz clic en la pestaña Índices. En Cloud Console, se muestra una lista de índices.
De manera opcional, para obtener detalles sobre un índice, como las columnas que incluye, haz clic en el nombre del índice.
gcloud
Usa el comando gcloud spanner databases ddl describe
:
gcloud spanner databases ddl describe DATABASE \
--instance=INSTANCE
La herramienta de gcloud
imprime las declaraciones del Lenguaje de definición de datos (DDL) para crear los índices y las tablas de la base de datos. Las declaraciones CREATE
INDEX
describen los índices existentes. Por ejemplo:
--- |-
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY(SingerId)
---
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName)
Consulta con un índice específico
En las siguientes secciones, se explica cómo especificar un índice en una instrucción de SQL y con la interfaz de lectura para Cloud Spanner. En los ejemplos de estas secciones, se supone que agregaste una columna MarketingBudget
a la tabla Albums
y que creaste un índice llamado AlbumsByAlbumTitle
:
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
MarketingBudget INT64,
) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
Especifica un índice en una instrucción de SQL
Cuando usas SQL para consultar una tabla de Cloud Spanner, este usa de forma automática cualquier índice que pueda hacer que la consulta sea más eficaz. Como resultado, en general, no es necesario especificar un índice para las consultas de SQL.
Sin embargo, en algunos casos, Cloud Spanner podría elegir un índice que aumente la latencia de las consultas. Si seguiste los pasos para solucionar problemas de las regresiones de rendimiento y confirmaste que tiene sentido probar otro índice para la consulta, puedes especificarlo como parte de tu consulta.
Si deseas especificar un índice en una instrucción de SQL, usa FORCE_INDEX
para proporcionar una directiva de índice. Las directivas de índice usan la sintaxis que se menciona a continuación:
FROM MyTable@{FORCE_INDEX=MyTableIndex}
También se puede usar una directiva de índice para indicar a Cloud Spanner que analice la tabla base, en lugar de usar un índice:
FROM MyTable@{FORCE_INDEX=_BASE_TABLE}
En el siguiente ejemplo, se muestra una consulta de SQL que especifica un índice:
SELECT AlbumId, AlbumTitle, MarketingBudget
FROM Albums@{FORCE_INDEX=AlbumsByAlbumTitle}
WHERE AlbumTitle >= "Aardvark" AND AlbumTitle < "Goo";
Una directiva de índice puede obligar al procesador de consultas de Cloud Spanner a leer columnas adicionales que la consulta requiere, pero que no se almacenan en el índice.
El procesador de consultas recupera estas columnas mediante la unión del índice y la tabla base. Si deseas evitar esta unión adicional, usa una cláusula STORING
para almacenar las columnas adicionales en el índice.
Por ejemplo, en la muestra anterior, la columna MarketingBudget
no se almacena en el índice, pero la consulta de SQL selecciona esta columna. Como resultado, Cloud Spanner debe buscar la columna MarketingBudget
en la tabla base y, luego, unirla a los datos del índice para mostrar los resultados de la consulta.
Cloud Spanner genera un error si la directiva de índice tiene alguno de los siguientes problemas:
- El índice no existe.
- El índice está en una tabla base diferente.
- A la consulta le falta una expresión de filtrado
NULL
obligatoria para un índiceNULL_FILTERED
.
En los siguientes ejemplos, se muestra cómo escribir y ejecutar consultas que recuperan los valores de AlbumId
, AlbumTitle
y MarketingBudget
mediante el índice AlbumsByAlbumTitle
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Especifica un índice en la interfaz de lectura
Cuando usas la interfaz de lectura en Cloud Spanner y deseas que este use un índice, debes especificar el índice. La interfaz de lectura no selecciona el índice de forma automática.
Además, tu índice debe contener todos los datos que aparecen en los resultados de la consulta, sin incluir las columnas que forman parte de la clave primaria. Esta restricción existe porque la interfaz de lectura no es compatible con combinaciones entre el índice y la tabla base. Si necesitas incluir otras columnas en los resultados de la consulta, puedes elegir entre las siguientes opciones:
- Usa una cláusula
STORING
para almacenar las columnas adicionales en el índice. - Realiza consultas sin incluir las columnas adicionales y usa las claves primarias para enviar otra consulta que lea las columnas adicionales.
Cloud Spanner muestra los valores del índice en orden ascendente por clave de índice. Para recuperar los valores en orden descendente, sigue estos pasos:
Anota la clave de índice con
DESC
. Por ejemplo:CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle DESC);
La anotación
DESC
se aplica a una sola clave de índice. Si el índice incluye más de una clave y quieres que los resultados de la consulta aparezcan en orden descendente según todas las claves, incluye una anotaciónDESC
para cada clave.Si la lectura especifica un rango de clave, asegúrate de que el rango de clave también esté en orden descendente. En otras palabras, el valor de la clave de inicio debe ser mayor que el valor de la clave de cierre.
En el siguiente ejemplo, se muestra cómo recuperar los valores de AlbumId
y AlbumTitle
con el índice AlbumsByAlbumTitle
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Cláusula STORING
De forma opcional, puedes usar la cláusula STORING
para almacenar una copia de una columna en el índice. Este tipo de índice proporciona ventajas para las consultas y las llamadas de operación lectura que usan el índice, a costa de usar almacenamiento adicional:
- Las consultas de SQL que usan el índice y seleccionan las columnas almacenadas en la cláusula
STORING
no requieren una unión adicional para la tabla base. - Las llamadas de operación de lectura que usan el índice pueden leer las columnas almacenadas en la cláusula
STORING
.
Por ejemplo, supongamos que creaste una versión alternativa de AlbumsByAlbumTitle
que almacena una copia de la columna MarketingBudget
en el índice (ten en cuenta la cláusula STORING
en negrita):
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget);
Con el índice AlbumsByAlbumTitle
anterior, Cloud Spanner debe unir el índice con la tabla base y, luego, recuperar la columna de la tabla base. Con el nuevo índice AlbumsByAlbumTitle2
, Cloud Spanner lee la columna directamente desde el índice, que es más eficiente.
Si usas la interfaz de lectura, en lugar de SQL, el nuevo índice AlbumsByAlbumTitle2
también te permite leer directamente la columna MarketingBudget
:
C++
C#
Go
Java
Node.js
PHP
Python
Ruby
Indexa valores NULL
Según la configuración predeterminada, Cloud Spanner indexa los valores NULL
. Por ejemplo, recupera la definición del índice SingersByFirstLastName
en la tabla Singers
:
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
Todas las filas de Singers
se indexan, incluso si FirstName
o LastName
, o ambos, sean NULL
.
Cuando se indexan valores NULL
, puedes realizar consultas de SQL eficientes y operaciones de lectura de datos que incluyan valores NULL
. Por ejemplo, usa esta declaración de consulta de SQL para buscar todos los Singers
con un FirstName
NULL
:
SELECT s.SingerId, s.FirstName, s.LastName
FROM Singers@{FORCE_INDEX=SingersByFirstLastName} AS s
WHERE s.FirstName IS NULL;
Ordena por valores NULL
Cloud Spanner ordena NULL
como el valor más pequeño para cualquier tipo determinado. Para una columna en orden ascendente (ASC
), los valores NULL
se ordenan primero. Para una columna en orden descendente (DESC
), los valores NULL
se ordenan por último.
Inhabilita la indexación de valores NULL
Para inhabilitar la indexación de valores nulos, agrega la palabra clave NULL_FILTERED
a la definición del índice. Los índices NULL_FILTERED
son muy útiles para indexar columnas dispersas, en la mayoría de las filas contienen un valor NULL
. En estos casos, el índice NULL_FILTERED
puede ser bastante más pequeño y más eficaz de mantener que un índice normal que incluya valores NULL
.
Esta es una definición alternativa de SingersByFirstLastName
que no indexa valores NULL
:
CREATE NULL_FILTERED INDEX SingersByFirstLastNameNoNulls
ON Singers(FirstName, LastName);
La palabra clave NULL_FILTERED
se aplica a todas las columnas de clave de índice. No puedes especificar el filtro NULL
por columna.
Crear un índice NULL_FILTERED
evita que Cloud Spanner lo use para algunas consultas. Por ejemplo, Cloud Spanner no usa el índice con esta consulta, porque el índice omite cualquiera de las filas Singers
para las que LastName
es NULL
. Como resultado, el uso del índice evitaría que la consulta mostrara las filas correctas:
FROM Singers@{FORCE_INDEX=SingersByFirstLastNameNoNulls}
WHERE FirstName = "John";
Con el fin de permitir que Cloud Spanner use el índice, debes reescribir la consulta para que excluya las filas que también se excluyen del índice:
SELECT FirstName, LastName
FROM Singers@{FORCE_INDEX=SingersByFirstLastNameNoNulls}
WHERE FirstName = "John" AND LastName IS NOT NULL;
Índices únicos
Los índices se pueden declarar como UNIQUE
. Los índices UNIQUE
agregan una restricción a los datos que se indexan y que prohíben las entradas duplicadas para una clave de índice determinada.
Cloud Spanner aplica esta restricción durante la confirmación de la transacción.
En particular, no se confirmarán las transacciones que harían que existan varias entradas de índice para la misma clave.
Si una tabla contiene datos que no son UNIQUE
en ella, cuando intentes crear un índice UNIQUE
en ella, fallará.
Una nota sobre los índices UNIQUE NULL_FILTERED
Un índice UNIQUE NULL_FILTERED
no fuerza la unicidad de la clave de índice cuando una de las partes clave del índice, como mínimo, es NULL.
Por ejemplo, supongamos que creaste el siguiente índice y tabla:
CREATE TABLE ExampleTable (
Key1 INT64 NOT NULL,
Key2 INT64,
Key3 INT64,
Col1 INT64,
) PRIMARY KEY (Key1, Key2, Key3);
CREATE UNIQUE NULL_FILTERED INDEX ExampleIndex ON ExampleTable (Key1, Key2, Col1);
Las siguientes dos filas en ExampleTable
tienen los mismos valores para las claves de índice secundarias Key1
, Key2
y Col1
:
1, NULL, 1, 1
1, NULL, 2, 1
Dado que Key2
es NULL
, y el índice es NULL_FILTERED
, las filas no estarán presentes en el índice ExampleIndex
. Debido a que no se insertan en el índice, este no los rechazará por violar la unicidad en (Key1, Key2,
Col1)
.
Si deseas que el índice fuerce la unicidad de los valores de la tupla (Key1
, Key2
, Col1
), debes anotar Key2
con NOT NULL
en la definición de tabla o crear el índice sin NULL_FILTERED
.
Quita un índice
Usa la declaración DROP INDEX
para descartar un índice secundario de tu esquema.
Para descartar el índice llamado SingersByFirstLastName
, usa la siguiente declaración:
DROP INDEX SingersByFirstLastName;
¿Qué sigue?
- Obtén más información sobre las prácticas recomendadas de SQL para Cloud Spanner.
- Obtén más información sobre los planes de ejecución de consultas para Cloud Spanner.
- Descubre cómo solucionar problemas de regresiones de rendimiento en consultas de SQL.