En una base de datos de 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 rápidamente un álbum por título, debes crear un índice secundario en AlbumTitle
, de modo que Spanner no necesite analizar toda la tabla.
Si la búsqueda del ejemplo anterior se realiza dentro de una transacción de lectura y escritura,
entonces la búsqueda más eficiente también evita mantener bloqueos en toda la tabla,
lo que permite inserciones y actualizaciones simultáneas de la tabla en las filas que se encuentran fuera del
Rango de búsqueda de AlbumTitle
.
Además de los beneficios que aportan a las búsquedas, los índices secundarios también pueden ayudar a Spanner a ejecutar análisis de manera más eficiente, lo que permite análisis de índices en lugar de análisis de tablas completos.
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 (bases de datos de dialecto GoogleSQL) o la cláusulaINCLUDE
(bases de datos de dialecto PostgreSQL) de la definición del índice
Con el tiempo, Spanner analiza las tablas para garantizar que las se usan para las consultas correspondientes.
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 Spanner las instrucciones DDL para la tabla nueva y los nuevos índices en una sola solicitud.
En 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 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, Spanner reabastece o propaga automáticamente el índice para reflejar una vista actualizada. de los datos que se indexan. Spanner administra este proceso de reabastecimiento automáticamente, y el proceso se ejecuta en segundo plano usando recursos de nodos en prioridad. En la mayoría de los casos, no es posible acelerar el proceso (p. ej., agregando más nodos), y el reabastecimiento no afecta significativamente el rendimiento de la base de datos.
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 capacidad de procesamiento de la instancia
- La carga de la instancia
Para ver el progreso de un proceso de reabastecimiento de índices, 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 sentencia 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:
GoogleSQL
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
PostgreSQL
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:
GoogleSQL
CREATE INDEX SongsBySongName ON Songs(SongName);
PostgreSQL
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
:
GoogleSQL
CREATE INDEX SongsBySingerSongName ON Songs(SingerId, SongName),
INTERLEAVE IN Singers;
PostgreSQL
CREATE INDEX SongsBySingerSongName ON Songs(SingerId, SongName)
INTERLEAVE IN Singers;
Para indexar solo las canciones de un álbum en particular, ejecuta lo siguiente:
GoogleSQL
CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName),
INTERLEAVE IN Albums;
PostgreSQL
CREATE INDEX SongsBySingerAlbumSongName ON Songs(SingerId, AlbumId, SongName)
INTERLEAVE IN Albums;
Para indexar por orden descendente de SongName
, ejecuta lo siguiente:
GoogleSQL
CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC),
INTERLEAVE IN Albums;
PostgreSQL
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.
Verifica el progreso del reabastecimiento del índice
Console
En el menú de navegación de Spanner, haz clic en la pestaña Operaciones. El En la página Operaciones, se muestra una lista de las operaciones que se están ejecutando.
Busca la operación de reabastecimiento en la lista. Si aún se está ejecutando, el el indicador de progreso en la columna Hora de finalización muestra el porcentaje de la operación que se complete, como se muestra en la siguiente imagen:
gcloud
Usa gcloud spanner operations describe
.
para verificar el progreso de una operación.
Obtén el ID de operación:
gcloud spanner operations list --instance=INSTANCE-NAME \ --database=DATABASE-NAME --type=DATABASE_UPDATE_DDL
Reemplaza lo siguiente:
- INSTANCE-NAME por la instancia de Spanner de la fuente de datos.
- DATABASE-NAME por el nombre de la base de datos.
Notas de uso:
Para limitar la lista, especifica la marca
--filter
. Por ejemplo:--filter="metadata.name:example-db"
solo enumera las operaciones. en una base de datos específica.--filter="error:*"
solo enumera las operaciones de copia de seguridad que fallaron.
Para obtener información sobre la sintaxis de filtro, consulta Filtros de temas de gcloud. Para obtener información sobre cómo filtrar operaciones de copia de seguridad, consulta el campo
filter
en ListBackupOperationsRequest.La marca
--type
no distingue mayúsculas de minúsculas.
El resultado es similar al siguiente:
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
Ejecuta
gcloud spanner operations describe
:gcloud spanner operations describe \ --instance=INSTANCE-NAME \ --database=DATABASE-NAME \ projects/PROJECT-NAME/instances/INSTANCE-NAME/databases/DATABASE-NAME/operations/OPERATION_ID
Reemplaza lo siguiente:
- INSTANCE-NAME: Es el nombre de la instancia de Spanner.
- DATABASE-NAME: Es el nombre de la base de datos de Spanner.
- PROJECT-NAME: Es el nombre del proyecto.
- OPERATION-ID: Es el ID de la operación que deseas. de verificación.
En la sección
progress
del resultado, se muestra el porcentaje de la operación. que está completo. El resultado es similar al siguiente:done: true ... 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' ...
REST v1
Obtén el ID de operación:
gcloud spanner operations list --instance=INSTANCE-NAME
--database=DATABASE-NAME --type=DATABASE_UPDATE_DDL
Reemplaza lo siguiente:
- INSTANCE-NAME por la instancia de Spanner de la fuente de datos.
- DATABASE-NAME por el nombre de la base de datos
Antes de usar cualquiera de los datos de solicitud a continuación, realiza los siguientes reemplazos:
- PROJECT-ID: El ID del proyecto.
- INSTANCE-ID: El ID de la instancia.
- DATABASE-ID: Es el ID de la base de datos.
- OPERATION-ID: Es el ID de la operación.
Método HTTP y URL:
GET https://spanner.googleapis.com/v1/projects/PROJECT-ID/instances/INSTANCE-ID/databases/DATABASE-ID/operations/OPERATION-ID
Para enviar tu solicitud, expande una de estas opciones:
Deberías recibir una respuesta JSON similar a la que se muestra a continuación:
{ ... "progress": [ { "progressPercent": 100, "startTime": "2023-05-27T00:52:27.366688Z", "endTime": "2023-05-27T00:52:30.184845Z" }, { "progressPercent": 100, "startTime": "2023-05-27T00:52:30.184845Z", "endTime": "2023-05-27T00:52:40.750959Z" } ], ... "done": true, "response": { "@type": "type.googleapis.com/google.protobuf.Empty" } }
En el caso de gcloud
y REST, puedes encontrar el progreso de cada sentencia de reabastecimiento de índices en la sección progress
. Para cada instrucción en la matriz de instrucción,
hay un campo correspondiente en la matriz de progreso. Este orden del array de progreso corresponde al orden del array de instrucciones. Una vez que están disponibles,
Los campos startTime
, progressPercent
y endTime
se propagan según corresponda.
Ten en cuenta que el resultado no muestra una hora estimada en la que se completará el
el progreso se completará.
Si la operación tarda demasiado, puedes cancelarla. Para obtener más información, consulta Cancela la creación del índice.
Situaciones en las que se visualiza el progreso del reabastecimiento de índices
Existen diferentes situaciones que puedes encontrar cuando intentas verificar el progreso de un reabastecimiento de índice. Declaraciones de creación de índices que requieren un índice el reabastecimiento son parte de las operaciones de actualización del esquema, y puede haber que forman parte de una operación de actualización de esquema.
La primera situación es la más sencilla, que ocurre cuando la declaración de creación del índice
es la primera sentencia en la operación de actualización del esquema. Desde que se creó el índice
es la primera, es la primera que se procesa y ejecuta debido a
al orden de ejecución.
De inmediato, el campo startTime
de la declaración de creación del índice
se propaga con la hora de inicio de la operación de actualización del esquema. A continuación, el campo progressPercent
de la sentencia de creación del índice se propaga cuando el progreso del reabastecimiento del índice supera el 0%. Por último, el campo endTime
se propaga una vez
se confirma la instrucción.
La segunda situación es cuando la sentencia de creación de índice no es la primera sentencia en la operación de actualización del esquema. No se propagarán campos relacionados con la sentencia de creación de índices hasta que se hayan confirmado las sentencias anteriores debido al orden de ejecución.
Al igual que en la situación anterior, una vez que se confirman las instrucciones anteriores, primero se propaga el campo startTime
de la instrucción de creación de índice, seguido del campo progressPercent
. Por último, el campo endTime
se completa una vez que
finaliza la confirmación.
Cancelar la creación del índice
Puedes usar Google Cloud CLI 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 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
Ver los índices existentes
Para ver información sobre índices existentes en una base de datos, puedes usar el La consola de Google Cloud o Google Cloud CLI:
Console
Ve a la página Instancias de Spanner en la consola de Google Cloud.
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 la consola de Google Cloud, se muestra una lista los í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 CLI de gcloud imprime las sentencias del Lenguaje de definición de datos (DDL) para crear los índices y las tablas de la base de datos. Las sentencias 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 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
:
GoogleSQL
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);
PostgreSQL
CREATE TABLE Albums (
SingerId BIGINT NOT NULL,
AlbumId BIGINT NOT NULL,
AlbumTitle VARCHAR,
MarketingBudget BIGINT,
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 Spanner, este servicio
y usa cualquier índice que pueda aumentar la eficacia de la consulta. Como resultado,
no necesitas especificar un índice
para las consultas en SQL. Sin embargo,
para consultas que son fundamentales para tu carga de trabajo, Google te recomienda usar
FORCE_INDEX
en tus instrucciones de SQL para lograr un rendimiento más coherente.
En algunos casos, 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.
Para especificar un índice en una instrucción de SQL, usa FORCE_INDEX
Sugerencia para proporcionar una directiva de índice. Las directivas de índice usan la sintaxis que se menciona a continuación:
GoogleSQL
FROM MyTable@{FORCE_INDEX=MyTableIndex}
PostgreSQL
FROM MyTable /*@ FORCE_INDEX = MyTableIndex */
También puedes usar una directiva de índice para indicarle a Spanner que analice la base en lugar de usar un índice:
GoogleSQL
FROM MyTable@{FORCE_INDEX=_BASE_TABLE}
PostgreSQL
FROM MyTable /*@ FORCE_INDEX = _BASE_TABLE */
En el siguiente ejemplo, se muestra una consulta de SQL que especifica un índice:
GoogleSQL
SELECT AlbumId, AlbumTitle, MarketingBudget
FROM Albums@{FORCE_INDEX=AlbumsByAlbumTitle}
WHERE AlbumTitle >= "Aardvark" AND AlbumTitle < "Goo";
PostgreSQL
SELECT AlbumId, AlbumTitle, MarketingBudget
FROM Albums /*@ FORCE_INDEX = AlbumsByAlbumTitle */
WHERE AlbumTitle >= 'Aardvark' AND AlbumTitle < 'Goo';
Una directiva de índice podría forzar la lectura del procesador de consultas de Spanner
columnas adicionales requeridas por la consulta, 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. Para evitar esta unión adicional, usa un
Cláusula STORING
(bases de datos del dialecto GoogleSQL) o INCLUDE
(bases de datos del dialecto PostgreSQL) para
almacenar las columnas adicionales en el índice.
En el ejemplo anterior, la columna MarketingBudget
no está
almacenados en el índice, pero la consulta en SQL selecciona esta columna. Como resultado, 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.
Spanner genera un error si la directiva de índice tiene alguna de las siguientes opciones 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 de Spanner y quieres para usar un índice, debes especificarlo. 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
oINCLUDE
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.
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
Crea un índice para análisis de solo índice
De forma opcional, puedes usar la cláusula STORING
(para bases de datos de dialecto GoogleSQL) o la cláusula INCLUDE
(para bases de datos de dialecto PostgreSQL) 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:
- Consultas en SQL que usan el índice y seleccionan las columnas almacenadas en el
STORING
oINCLUDE
no requieren una unión adicional a la tabla base. - Las llamadas a
read()
que usan el índice pueden leer las columnas almacenadas por la cláusulaSTORING
/INCLUDE
.
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 el
Cláusulas STORING
o INCLUDE
en negrita):
GoogleSQL
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget);
PostgreSQL
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) INCLUDE (MarketingBudget);
Con el índice AlbumsByAlbumTitle
anterior, Spanner debe unir el índice con la tabla base y, luego, recuperar la columna de la tabla base. Con la nueva
AlbumsByAlbumTitle2
, Spanner lee la columna directamente del
í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
Cómo alterar un índice
Puedes usar la sentencia ALTER INDEX
para agregar columnas adicionales
en un índice existente o descartar columnas. Esta
Puede actualizar la lista de columnas definida por la cláusula STORING
.
(bases de datos del dialecto GoogleSQL) o la cláusula INCLUDE
(bases de datos del dialecto PostgreSQL) cuando creas la
índice. No puedes usar esta sentencia para agregar columnas a la clave de índice ni quitarlas. Por ejemplo, en lugar de crear una nueva
índice AlbumsByAlbumTitle2
, puedes usar ALTER INDEX
para agregar
en AlbumsByAlbumTitle
, como se muestra en el siguiente ejemplo:
GoogleSQL
ALTER INDEX AlbumsByAlbumTitle ADD STORED COLUMN MarketingBudget
PostgreSQL
ALTER INDEX AlbumsByAlbumTitle ADD INCLUDE COLUMN MarketingBudget
Cuando agregas una columna nueva a un índice existente, Spanner
usa un proceso de reabastecimiento en segundo plano. Mientras el reabastecimiento está en curso,
la columna del índice no es legible, así que es posible que no
un aumento del rendimiento. Puedes usar el comando gcloud spanner operations
para enumerar la operación de larga duración y ver su estado.
Para obtener más información, consulta Cómo describir una operación.
También puedes usar Cancelar operación para cancelar una operación en ejecución.
Una vez que se completa el reabastecimiento, Spanner agrega la columna al índice. A medida que el índice crece, es posible que se ralenticen las consultas que lo usan.
En el siguiente ejemplo, se muestra cómo quitar una columna de un índice:
GoogleSQL
ALTER INDEX AlbumsByAlbumTitle DROP STORED COLUMN MarketingBudget
PostgreSQL
ALTER INDEX AlbumsByAlbumTitle DROP INCLUDE COLUMN MarketingBudget
Índice de valores NULL
De forma predeterminada, 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
:
GoogleSQL
SELECT s.SingerId, s.FirstName, s.LastName
FROM Singers@{FORCE_INDEX=SingersByFirstLastName} AS s
WHERE s.FirstName IS NULL;
PostgreSQL
SELECT s.SingerId, s.FirstName, s.LastName
FROM Singers /* @ FORCE_INDEX = SingersByFirstLastName */ AS s
WHERE s.FirstName IS NULL;
Ordena por valores NULL
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
GoogleSQL
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.
PostgreSQL
Para filtrar filas con valores nulos en una o más columnas indexadas, usa el predicado WHERE COLUMN IS NOT NULL
.
Los índices filtrados por nulos son muy útiles para indexar columnas dispersas, en la mayoría de las filas contienen un valor NULL
. En estos casos, el índice filtrado nulo 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 INDEX SingersByFirstLastNameNoNulls
ON Singers(FirstName, LastName)
WHERE FirstName IS NOT NULL
AND LastName IS NOT NULL;
Filtrar los valores NULL
evita que Spanner los use para algunas
consultas. Por ejemplo, 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:
GoogleSQL
FROM Singers@{FORCE_INDEX=SingersByFirstLastNameNoNulls}
WHERE FirstName = "John";
PostgreSQL
FROM Singers /*@ FORCE_INDEX = SingersByFirstLastNameNoNulls */
WHERE FirstName = 'John';
Para permitir que Spanner use el índice, debes volver a escribir la consulta de modo que Excluye las filas que también se excluyen del índice:
GoogleSQL
SELECT FirstName, LastName
FROM Singers@{FORCE_INDEX=SingersByFirstLastNameNoNulls}
WHERE FirstName = 'John' AND LastName IS NOT NULL;
PostgreSQL
SELECT FirstName, LastName
FROM Singers /*@ FORCE_INDEX = SingersByFirstLastNameNoNulls */
WHERE FirstName = 'John' AND LastName IS NOT NULL;
Indexa campos de proto
Usa columnas generadas para indexar
en búferes de protocolo almacenados en columnas PROTO
, siempre que los campos
que se indexan usan los tipos de datos primitivos o ENUM
.
Si defines un índice en un campo de mensaje de protocolo, no puedes modificar ni quitar ese campo desde el esquema proto. Para obtener más información, consulta Actualizaciones de esquemas que contienen un índice en campos de proto.
El siguiente es un ejemplo de la tabla Singers
con un proto SingerInfo
mensaje. Para definir un índice en el campo nationality
de PROTO
,
debes crear una columna generada almacenada:
GoogleSQL
CREATE PROTO BUNDLE (googlesql.example.SingerInfo, googlesql.example.SingerInfo.Residence);
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
...
SingerInfo googlesql.example.SingerInfo,
SingerNationality STRING(MAX) AS (SingerInfo.nationality) STORED
) PRIMARY KEY (SingerId);
Tiene la siguiente definición del tipo de proto googlesql.example.SingerInfo
:
GoogleSQL
package googlesql.example;
message SingerInfo {
optional string nationality = 1;
repeated Residence residence = 2;
message Residence {
required int64 start_year = 1;
optional int64 end_year = 2;
optional string city = 3;
optional string country = 4;
}
}
Luego, define un índice en el campo nationality
del proto:
GoogleSQL
CREATE INDEX SingersByNationality ON Singers(SingerNationality);
La siguiente consulta en SQL lee los datos con el índice anterior:
GoogleSQL
SELECT s.SingerId, s.FirstName
FROM Singers AS s
WHERE s.SingerNationality = "English";
Notas:
- Usa una directiva de índice para acceder a los índices en la campos de columnas del búfer de protocolo.
- No puedes crear un índice en campos de búfer de protocolo repetidos.
Actualizaciones de los esquemas que contienen un índice en campos proto
Si defines un índice en un campo de mensaje de protocolo, no podrás modificar ni quitar ese campo del esquema de proto. Esto se debe a que, después de definir el índice, la verificación de tipos se realiza cada vez que se actualiza el esquema. Spanner captura la información de tipo de todos los campos de la ruta que se usan en la definición del índice.
Í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.
Spanner aplica esta restricción en el momento de 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:
GoogleSQL
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);
PostgreSQL
CREATE TABLE ExampleTable (
Key1 BIGINT NOT NULL,
Key2 BIGINT,
Key3 BIGINT,
Col1 BIGINT,
PRIMARY KEY (Key1, Key2, Key3)
);
CREATE UNIQUE INDEX ExampleIndex ON ExampleTable (Key1, Key2, Col1)
WHERE Key1 IS NOT NULL
AND Key2 IS NOT NULL
AND Col1 IS NOT NULL;
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 se filtra como nulo, las filas no estarán presentes en el índice ExampleIndex
. Debido a que no se insertan en el
índice, este no los rechazará por incumplir la unicidad en (Key1, Key2,
Col1)
.
Si quieres que el índice aplique la unicidad de los valores de la tupla (Key1
,
Key2
, Col1
), entonces debes anotar Key2
con NOT NULL
en la tabla
definición o crear el índice sin filtrar los valores nulos.
Cómo descartar 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;
Índice para un análisis más rápido
Cuando Spanner necesita realizar un análisis de tabla (en lugar de una búsqueda indexada) para recuperar valores de una o más columnas, puedes recibir resultados más rápidos si existe un índice para esas columnas y en el orden que especifica la consulta. Si realizas con frecuencia consultas que requieran análisis, crea índices secundarios que te ayuden para que estos análisis se realicen de forma más eficiente.
En particular, si necesitas que Spanner analice con frecuencia la clave principal de una tabla o algún otro índice en orden inverso, puedes aumentar su eficiencia a través de un índice secundario que haga que el orden elegido sea explícito.
Por ejemplo, la siguiente consulta siempre muestra un resultado rápido, a pesar de que
Spanner necesita analizar Songs
para encontrar el valor más bajo de
SongId
:
SELECT SongId FROM Songs LIMIT 1;
SongId
es la clave primaria de la tabla, almacenada (como con todas las claves primarias)
en orden ascendente. Spanner puede analizar el índice de esa clave y encontrar
el primer resultado rápidamente.
Sin embargo, sin la ayuda de un índice secundario, la siguiente consulta no se mostraría tan rápido, en especial, si Songs
contiene muchos datos:
SELECT SongId FROM Songs ORDER BY SongId DESC LIMIT 1;
Aunque SongId
es la clave primaria de la tabla, Spanner no tiene ninguna manera de recuperar el valor más alto de la columna sin recurrir a un análisis completo de la tabla.
Agregar el siguiente índice permitiría que esta consulta muestre más rápidamente:
CREATE INDEX SongIdDesc On Songs(SongId DESC);
Con este índice implementado, Spanner lo usaría para mostrar un para la segunda consulta mucho más rápido.
¿Qué sigue?
- Obtén más información sobre las prácticas recomendadas de SQL para Spanner.
- Obtén más información sobre los planes de ejecución de consultas para Spanner.
- Descubre cómo solucionar problemas de regresiones de rendimiento en consultas de SQL.