Recomendaciones sobre SQL

Como se describe en Planes de ejecución de consultas, el compilador de SQL transforma una instrucción de SQL en un plan de ejecución de consultas, que se utiliza para obtener los resultados de la consulta. En esta página, se describen las prácticas recomendadas para crear instrucciones de SQL que ayuden a Spanner a encontrar planes de ejecución eficientes.

En las instrucciones de SQL de ejemplo que se muestran en esta página, se usa el siguiente esquema de muestra:

GoogleSQL

CREATE TABLE Singers (
 SingerId   INT64 NOT NULL,
 FirstName  STRING(1024),
 LastName   STRING(1024),
 SingerInfo BYTES(MAX),
 BirthDate  DATE
) PRIMARY KEY (SingerId);

CREATE TABLE Albums (
 SingerId     INT64 NOT NULL,
 AlbumId      INT64 NOT NULL,
 AlbumTitle   STRING(MAX),
 ReleaseDate  DATE
) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

Para obtener la referencia completa de SQL, consulta Expresiones, funciones y operadores, Estructura léxica y sintaxis y la página sobre la sintaxis de instrucción.

PostgreSQL

CREATE TABLE Singers (
 SingerId   BIGINT PRIMARY KEY,
 FirstName  VARCHAR(1024),
 LastName   VARCHAR(1024),
 SingerInfo BYTEA,
 BirthDate  TIMESTAMPTZ
);

CREATE TABLE Albums (
 SingerId        BIGINT NOT NULL,
 AlbumId         BIGINT NOT NULL,
 AlbumTitle      VARCHAR(1024),
 ReleaseDate     DATE,
 PRIMARY KEY(SingerId, AlbumId),
 FOREIGN KEY (SingerId) REFERENCES Singers(SingerId)
) INTERLEAVE IN PARENT Singers ON DELETE CASCADE;

Para obtener más información, consulta El lenguaje de PostgreSQL en Spanner.

Usa parámetros de consulta

Spanner admite parámetros de consulta para aumentar el rendimiento y ayudar a evitar la inyección de SQL cuando las consultas se crean mediante entradas del usuario. Puedes usar los parámetros de consulta como sustitutos de expresiones arbitrarias, pero no como sustitutos de identificadores, nombres de columnas, nombres de tablas y otras partes de la consulta.

Los parámetros pueden aparecer en cualquier lugar donde se espere un valor literal. El mismo nombre de parámetro se puede usar más de una vez en una sola instrucción de SQL.

En resumen, los parámetros de consulta admiten la ejecución de consultas de las siguientes maneras:

  • Planes optimizados con anterioridad: Las consultas que usan parámetros se pueden ejecutar más rápido en cada invocación, ya que la parametrización facilita a Spanner almacenar en caché el plan de ejecución.
  • Composición simplificada de la consulta: No es necesario escapar valores de string cuando los proporciones en los parámetros de consulta. Los parámetros de consulta también reducen el riesgo de errores de sintaxis.
  • Seguridad: Los parámetros de consulta hacen que tus consultas sean más seguras, ya que te protegen de varios ataques de inyección de SQL. Esta protección es importante en particular para las consultas que creas a partir de las entradas del usuario.

Comprende cómo Spanner ejecuta consultas

Spanner te permite consultar bases de datos mediante instrucciones de SQL declarativas que especifican qué datos deseas recuperar. Si deseas comprender cómo Spanner obtiene los resultados, examina el plan de ejecución de la consulta. Un plan de ejecución de consultas muestra el costo de procesamiento asociado con cada paso de la consulta. Con esos costos, puedes depurar los problemas de rendimiento de las consultas y optimizar tu consulta. Para obtener más información, visita Planes de ejecución de consultas.

Puedes recuperar planes de ejecución de consultas a través de la consola de Google Cloud o las bibliotecas cliente.

A fin de obtener un plan de ejecución de consultas para una consulta específica con la consola de Google Cloud, sigue estos pasos:

  1. Abre la página Instancias de Spanner.

    Ir a Instancias de Spanner

  2. Selecciona los nombres de la instancia de Spanner y la base de datos que deseas consultar.

  3. Haz clic en Spanner Studio en el panel de navegación izquierdo.

  4. Escribe la consulta en el campo de texto y haz clic en Ejecutar consulta.

  5. Haz clic en Explicación
    . La consola de Google Cloud muestra un plan de ejecución visual para tu consulta.

    Captura de pantalla del plan de ejecución visual en la consola de Cloud

Si quieres obtener más información sobre cómo comprender los planes visuales y usarlos para depurar tus consultas, revisa Ajusta una consulta con el visualizador del plan de consultas.

También puedes ver muestras de planes de consultas históricos y comparar el rendimiento de una consulta a lo largo del tiempo para ciertas consultas. Para obtener más información, consulta Planes de consulta de muestra.

Usa índices secundarios

Al igual que otras bases de datos relacionales, Spanner ofrece índices secundarios, que puedes usar para recuperar datos mediante una instrucción de SQL o la interfaz de lectura de Spanner. La forma más común de recuperar datos de un índice es usar Spanner Studio. Usar un índice secundario en una consulta en SQL te permite especificar cómo quieres que Spanner obtenga los resultados. Especificar un índice secundario puede acelerar la ejecución de consultas.

Por ejemplo, supongamos que deseas recuperar los ID de todos los cantantes con un apellido específico. Se puede escribir una consulta de SQL de este tipo de la siguiente forma:

SELECT s.SingerId
FROM Singers AS s
WHERE s.LastName = 'Smith';

Esta consulta mostrará los resultados que esperas, pero podría tardar mucho tiempo en hacerlo. El tiempo dependerá de la cantidad de filas de la tabla Singers y de cuántas satisfagan el predicado WHERE s.LastName = 'Smith'. Si no hay ningún índice secundario que contenga la columna LastName desde la cual leer, el plan de consulta leerá toda la tabla Singers para encontrar filas que coincidan con el predicado. La lectura de toda la tabla se denomina análisis completo de la tabla. Un análisis completo de la tabla es una forma costosa de obtener resultados cuando la tabla contiene solo un pequeño porcentaje de Singers con ese apellido.

Para mejorar el rendimiento de esta consulta, define un índice secundario en la columna de apellido:

CREATE INDEX SingersByLastName ON Singers (LastName);

Debido a que el índice secundario SingersByLastName contiene la columna de tabla indexada LastName y la columna de clave primaria SingerId, Spanner puede recuperar todos los datos de la tabla de índice mucho más pequeña en lugar de analizar la tabla Singers completa.

En esta situación, Spanner usa de forma automática el índice secundario SingersByLastName cuando ejecuta la consulta (siempre y cuando hayan transcurrido tres días desde la creación de la base de datos; consulta Nota sobre las bases de datos nuevas). Sin embargo, es mejor especificar de forma explícita una directiva de índice en la cláusula FROM para indicarle a Spanner que use ese índice:

GoogleSQL

SELECT s.SingerId
FROM Singers@{FORCE_INDEX=SingersByLastName} AS s
WHERE s.LastName = 'Smith';

PostgreSQL

 SELECT s.SingerId
FROM Singers /*@ FORCE_INDEX=SingersByLastName */ AS s
WHERE s.LastName = 'Smith';

Supongamos que también deseas recuperar el nombre del cantante, además del ID. Aunque la columna FirstName no está incluida en el índice, aún debes especificar la directiva de índice como antes:

GoogleSQL

SELECT s.SingerId, s.FirstName
FROM Singers@{FORCE_INDEX=SingersByLastName} AS s
WHERE s.LastName = 'Smith';

PostgreSQL

SELECT s.SingerId, s.FirstName
FROM Singers /*@ FORCE_INDEX=SingersByLastName */ AS s
WHERE s.LastName = 'Smith';

Aún obtienes un beneficio de rendimiento por usar el índice, ya que Spanner no necesita realizar un análisis completo de la tabla cuando ejecuta el plan de consultas. En cambio, selecciona el subconjunto de filas que satisfacen el predicado del índice SingersByLastName y, luego, realiza una búsqueda desde la tabla base Singers a fin de recuperar el primer nombre solo para ese subconjunto de filas.

Si deseas que Spanner no tenga que recuperar ninguna fila de la tabla base, puedes almacenar una copia de la columna FirstName en el índice:

GoogleSQL

CREATE INDEX SingersByLastName ON Singers (LastName) STORING (FirstName);

PostgreSQL

CREATE INDEX SingersByLastName ON Singers (LastName) INCLUDE (FirstName);

Usar una cláusula STORING (para el dialecto GoogleSQL) o una cláusula INCLUDE (para el dialecto PostgreSQL) como esta cuesta almacenamiento adicional, pero proporciona las siguientes ventajas:

  • Las consultas de SQL que usan el índice y seleccionan las columnas almacenadas en la cláusula STORING o INCLUDE no requieren una unión adicional a la tabla base.
  • Las llamadas de lectura que usan el índice pueden leer las columnas almacenadas en la cláusula STORING o INCLUDE.

En los ejemplos anteriores, se ilustra cómo los índices secundarios pueden acelerar las consultas cuando las filas que eligió la cláusula WHERE de una consulta se pueden identificar con rapidez mediante el índice secundario.

Otra situación en la que los índices secundarios pueden ofrecer beneficios de rendimiento es para determinadas consultas que muestran resultados ordenados. Por ejemplo, supongamos que deseas recuperar todos los títulos de álbumes y sus fechas de lanzamiento en orden ascendente por fecha de lanzamiento y orden descendente según el título del álbum. Podrías escribir una consulta en SQL de la siguiente manera:

SELECT a.AlbumTitle, a.ReleaseDate
FROM Albums AS a
ORDER BY a.ReleaseDate, a.AlbumTitle DESC;

Sin un índice secundario, esta consulta requiere un paso de clasificación potencialmente costoso en el plan de ejecución. Para acelerar la ejecución de consultas, define este índice secundario:

CREATE INDEX AlbumsByReleaseDateTitleDesc on Albums (ReleaseDate, AlbumTitle DESC);

Luego, vuelve a escribir la consulta para usar el índice secundario:

GoogleSQL

SELECT a.AlbumTitle, a.ReleaseDate
FROM Albums@{FORCE_INDEX=AlbumsByReleaseDateTitleDesc} AS a
ORDER BY a.ReleaseDate, a.AlbumTitle DESC;

PostgreSQL

SELECT a.AlbumTitle, a.ReleaseDate
FROM Albums /*@ FORCE_INDEX=AlbumsByReleaseDateTitleDesc */ AS s
ORDER BY a.ReleaseDate, a.AlbumTitle DESC;

Esta definición de índice y consulta cumple con los siguientes criterios:

  • Para quitar el paso de ordenamiento, asegúrate de que la lista de columnas de la cláusula ORDER BY sea un prefijo de la lista de claves de índice.
  • A fin de evitar una unión desde la tabla base para recuperar las columnas faltantes, asegúrate de que el índice cubra todas las columnas de la tabla que usa la consulta.

Aunque los índices secundarios pueden acelerar las consultas comunes, agregar índices secundarios puede agregar latencia a las operaciones de confirmación, ya que cada índice secundario suele requerir la participación de un nodo adicional en cada confirmación. Para la mayoría de las cargas de trabajo, está bien tener unos pocos índices secundarios. Sin embargo, debes considerar si tienes que preocuparte más por la latencia de lectura o escritura y qué operaciones son más importantes para tu carga de trabajo. Compara tu carga de trabajo para asegurarte de que funcione como esperas.

Para obtener la referencia completa de los índices secundarios, consulta la página sobre los índices secundarios.

Optimiza los análisis

Ciertas consultas de Spanner pueden beneficiarse del uso de un método de procesamiento por lotes cuando se analizan datos en lugar del método de procesamiento orientado a filas más común. El procesamiento de análisis en lotes es una forma más eficiente de procesar grandes volúmenes de datos a la vez y permite que las consultas reduzcan la latencia y el uso de CPU.

La operación de análisis de Spanner siempre inicia la ejecución en modo orientado a filas. Durante este tiempo, Spanner recopila varias métricas del entorno de ejecución. Luego, Spanner aplica un conjunto de heurísticas en función del resultado de estas métricas para determinar el modo de análisis óptimo. Cuando corresponda, Spanner cambia a un modo de procesamiento por lotes para ayudar a mejorar la capacidad de procesamiento y el rendimiento del análisis.

Casos de uso comunes

Por lo general, las consultas con las siguientes características se benefician del uso del procesamiento orientado por lotes:

  • Análisis grandes de datos actualizados con poca frecuencia
  • Analiza con predicados en columnas de ancho fijo.
  • Análisis con recuentos de búsquedas elevados. (Una búsqueda usa un índice para recuperar registros).

Casos de uso sin mejoras de rendimiento

No todas las consultas se benefician del procesamiento orientado por lotes. Los siguientes tipos de consultas tienen un mejor rendimiento con el procesamiento de análisis orientado a las filas:

  • Consultas de búsqueda de puntos: consultas que solo recuperan una fila.
  • Consultas de análisis pequeñas: análisis de tablas que solo analizan algunas filas, a menos que tengan grandes recuentos de búsquedas.
  • Consultas que usan LIMIT.
  • Consultas que leen datos de deserción alta: consultas en las que más del 10% de los datos leídos se actualiza con frecuencia.
  • Consultas con filas que contienen valores grandes: las filas de valores grandes son aquellas que contienen valores mayores a 32,000 bytes (compresión previa) en una sola columna.

Cómo verificar el método de análisis que usa una consulta

Para verificar si tu consulta usa procesamiento orientado por lotes, procesamiento orientado a filas o si cambia de forma automática entre los dos métodos de análisis, haz lo siguiente:

  1. Ve a la página Instancias de Spanner en la consola de Google Cloud.

    Ir a la página Instancias

  2. Haz clic en el nombre de la instancia con la consulta que quieres investigar.

  3. En la tabla Bases de datos, haz clic en la base de datos con la consulta que quieres investigar.

  4. En el menú de navegación, haz clic en Spanner Studio.

  5. Haz clic en Nueva pestaña del editor de SQL o Nueva pestaña para abrir una pestaña nueva.

  6. Escribe tu consulta cuando aparezca el editor de consultas.

  7. Haz clic en Ejecutar.

    Spanner ejecuta la consulta y muestra los resultados.

  8. Haz clic en la pestaña Explicación debajo del editor de consultas.

    Spanner muestra un visualizador del plan de ejecución del plan de consultas. Cada tarjeta del gráfico representa un iterador.

  9. Haz clic en la tarjeta de iterador Análisis de la tabla para abrir un panel de información.

    En el panel de información, se muestra información contextual sobre el análisis seleccionado. El método de escaneo se muestra en esta tarjeta. Automático indica que Spanner determina el método de análisis. Otros valores posibles incluyen Vectorizado para procesamiento orientado por lotes y Escalar para el procesamiento orientado a filas.

    Captura de pantalla de una tarjeta de escaneo de tabla que muestra el método de análisis como Automático

Cómo aplicar de manera forzosa el método de análisis que usa una consulta

Para optimizar el rendimiento de las consultas, Spanner elige el método de análisis óptimo para tu consulta. Te recomendamos que utilices este método de búsqueda predeterminado. Sin embargo, puede haber situaciones en las que quizás desees aplicar un tipo específico de método de análisis.

Cómo aplicar el análisis orientado por lotes

Puedes aplicar el análisis por lotes a nivel de la tabla y de la instrucción.

Para aplicar el método de análisis orientado por lotes a nivel de la tabla, usa una sugerencia de tabla en la consulta:

GoogleSQL

  SELECT ...
  FROM (t1@{SCAN_METHOD=BATCH} JOIN t2 ON ...)
  WHERE ...

PostgreSQL

  SELECT ...
  FROM (t1/*@ scan_method=batch */ JOIN t2 on ...)
  WHERE ...

Para aplicar el método de análisis orientado por lotes a nivel de declaración, usa una sugerencia de declaración en tu consulta:

GoogleSQL

  @{SCAN_METHOD=BATCH}
  SELECT ...
  FROM ...
  WHERE ...

PostgreSQL

  /*@ scan_method=batch */
  SELECT ...
  FROM ...
  WHERE ...

Cómo inhabilitar el análisis automático y aplicar el análisis orientado a filas

Aunque no recomendamos inhabilitar el método de análisis automático establecido por Spanner, puedes inhabilitarlo y usar el método de análisis orientado a filas para solucionar problemas, como diagnosticar la latencia.

Para inhabilitar el método de análisis automático y aplicar el procesamiento de filas a nivel de la tabla, usa una sugerencia de tabla en tu consulta:

GoogleSQL

  SELECT ...
  FROM (t1@{SCAN_METHOD=ROW} JOIN t2 ON ...)
  WHERE ...

PostgreSQL

  SELECT ...
  FROM (t1/*@ scan_method=row */ JOIN t2 on ...)
  WHERE ...

Para inhabilitar el método de análisis automático y aplicar el procesamiento de filas a nivel de la instrucción, usa una sugerencia de instrucción en tu consulta:

GoogleSQL

  @{SCAN_METHOD=ROW}
  SELECT ...
  FROM ...
  WHERE ...

PostgreSQL

  /*@ scan_method=row */
  SELECT ...
  FROM ...
  WHERE ...

Cómo optimizar las búsquedas de claves de rango

Un uso común de una consulta en SQL es leer varias filas de Spanner en función de una lista de claves conocidas.

Las siguientes prácticas recomendadas te ayudan a escribir consultas eficientes cuando se recuperan datos mediante un rango de claves:

  • Si la lista de claves es dispersa y no adyacente, usa los parámetros de consulta y UNNEST para construir tu consulta.

    Por ejemplo, si tu lista de claves es {1, 5, 1000}, escribe la consulta de la manera siguiente:

    GoogleSQL

    SELECT *
    FROM Table AS t
    WHERE t.Key IN UNNEST (@KeyList)
    

    PostgreSQL

    SELECT *
    FROM Table AS t
    WHERE t.Key IN UNNEST ($1)
    

    Notas:

    • El operador de arreglo UNNEST compacta un arreglo de entrada en filas de elementos.

    • El parámetro de consulta, que es @KeyList para GoogleSQL y $1 para PostgreSQL, puede acelerar la consulta, como se explica en la práctica recomendada anterior.

  • Si la lista de claves es adyacente y está dentro de un rango, especifica los límites inferior y superior del rango de claves en la cláusula WHERE.

    Por ejemplo, si tu lista de claves es {1,2,3,4,5}, construye la consulta de la siguiente manera:

    GoogleSQL

    SELECT *
    FROM Table AS t
    WHERE t.Key BETWEEN @min AND @max
    

    PostgreSQL

    SELECT *
    FROM Table AS t
    WHERE t.Key BETWEEN $1 AND $2
    

    Esta consulta solo es más eficiente si las claves del rango de claves son adyacentes. En otras palabras, si tu lista de claves es {1, 5, 1000}, no especifiques los límites inferior y superior como en la consulta anterior, ya que la consulta resultante analizará todos los valores entre 1 y 1,000.

Optimizar uniones

Las operaciones de unión pueden ser costosas, ya que pueden aumentar de manera significativa la cantidad de filas que tu consulta necesita analizar, lo que genera consultas más lentas. Además de las técnicas que sueles usar en otras bases de datos relacionales a fin de optimizar las consultas de unión, estas son algunas prácticas recomendadas para lograr una JOIN más eficiente cuando usas SQL de Spanner:

  • Si es posible, une los datos de las tablas intercaladas por clave primaria. Por ejemplo:

    SELECT s.FirstName, a.ReleaseDate
    FROM Singers AS s JOIN Albums AS a ON s.SingerId = a.SingerId;
    

    Se garantiza que las filas de la tabla intercalada Albums se almacenarán de manera física en las mismas divisiones que la fila superior en Singers, como se explica en Esquema y modelo de datos. Por lo tanto, las uniones pueden completarse de forma local sin enviar muchos datos a través de la red.

  • Usa la directiva de unión si quieres forzar el orden de la unión. Por ejemplo:

    GoogleSQL

    SELECT *
    FROM Singers AS s JOIN@{FORCE_JOIN_ORDER=TRUE} Albums AS a
    ON s.SingerId = a.Singerid
    WHERE s.LastName LIKE '%x%' AND a.AlbumTitle LIKE '%love%';
    

    PostgreSQL

    SELECT *
    FROM Singers AS s JOIN/*@ FORCE_JOIN_ORDER=TRUE */ Albums AS a
    ON s.SingerId = a.Singerid
    WHERE s.LastName LIKE '%x%' AND a.AlbumTitle LIKE '%love%';
    

    La directiva de unión FORCE_JOIN_ORDER le indica a Spanner que use el orden de unión especificado en la consulta (es decir, Singers JOIN Albums, no Albums JOIN Singers). Los resultados que se muestran son los mismos, sin importar el orden que elija Spanner. Sin embargo, es posible que quieras usar esta directiva de unión si observas en el plan de consulta que Spanner cambió el orden de unión y causó consecuencias no deseadas, como resultados intermedios más grandes, o perdió oportunidades de buscar filas.

  • Usa una directiva de unión para elegir una implementación de unión. Cuando usas SQL para consultar varias tablas, Spanner usa de forma automática un método de unión que probablemente aumente la eficiencia de la consulta. Sin embargo, Google te recomienda realizar pruebas con diferentes algoritmos de unión. Elegir el algoritmo de unión correcto puede mejorar la latencia, el consumo de memoria o ambos. En esta consulta, se muestra la sintaxis para usar una directiva JOIN con la sugerencia JOIN_METHOD para elegir un HASH JOIN:

    GoogleSQL

    SELECT *
    FROM Singers s JOIN@{JOIN_METHOD=HASH_JOIN} Albums AS a
    ON a.SingerId = a.SingerId
    

    PostgreSQL

    SELECT *
    FROM Singers s JOIN/*@ JOIN_METHOD=HASH_JOIN */ Albums AS a
    ON a.SingerId = a.SingerId
    
  • Si usas HASH JOIN o APPLY JOIN, y si tienes una cláusula WHERE que es muy selectiva en un lado de tu JOIN, coloca la tabla que produce la menor cantidad de filas como la primera tabla en la cláusula FROM de la unión. Esta estructura ayuda porque, por el momento, en HASH JOIN, Spanner siempre elige la tabla lateral izquierda como compilación y la tabla lateral derecha como sondeo. Del mismo modo, para APPLY JOIN, Spanner elige la tabla lateral izquierda como externa y la tabla lateral derecha como interna. Consulta más información sobre estos tipos de unión: Unión hash y Aplicar unión.

  • En las consultas que son fundamentales para tu carga de trabajo, especifica el método de unión y el orden de unión de mejor rendimiento en tus instrucciones de SQL para obtener un rendimiento más coherente.

Evita lecturas extensas en las transacciones de lectura y escritura

Las transacciones de lectura y escritura permiten una secuencia de cero o más lecturas o consultas de SQL y pueden incluir un conjunto de mutaciones antes de una llamada para confirmar. Para mantener la coherencia de tus datos, Spanner adquiere bloqueos cuando se leen y escriben filas en tus índices y tablas. Para obtener más información sobre el bloqueo, consulta Ciclo de vida de las operaciones de lectura y escritura.

Debido a la forma en que funciona el bloqueo en Spanner, realizar una consulta de lectura o de SQL que lea una gran cantidad de filas (por ejemplo, SELECT * FROM Singers) significa que ninguna otra transacción puede escribir en las filas que leíste hasta que se confirme o anule la transacción.

Además, debido a que la transacción procesa una gran cantidad de filas, es probable que demore más que una transacción que lee un rango de filas mucho más pequeño (por ejemplo, SELECT LastName FROM Singers WHERE SingerId = 7), lo que agrava aún más el problema y reduce la capacidad de procesamiento del sistema.

Por lo tanto, intenta evitar las operaciones de lectura grandes (por ejemplo, análisis completos de tablas o operaciones de unión masivas) en tus transacciones, a menos que estés dispuesto a aceptar una capacidad de procesamiento de escritura menor.

En algunos casos, el siguiente patrón puede producir mejores resultados:

  1. Realiza las lecturas grandes dentro de una transacción de solo lectura. Las transacciones de solo lectura permiten una capacidad de procesamiento agregada más alta porque no usan bloqueos.
  2. Opcional: Realiza cualquier procesamiento necesario en los datos que acabas de leer.
  3. Inicia una transacción de lectura y escritura.
  4. Verifica que los valores de las filas críticas no hayan cambiado desde que realizaste la transacción de solo lectura en el paso 1.
    • Si las filas cambiaron, revierte la transacción y comienza de nuevo en el paso 1.
    • Si todo sale bien, confirma tus mutaciones.

Una forma de asegurarte de evitar las lecturas grandes en las transacciones de lectura y escritura es observar los planes de ejecución que generan tus consultas.

Usa la cláusula ORDER BY para garantizar el orden de tus resultados de SQL

Si esperas un orden determinado para los resultados de una consulta SELECT, incluye de forma explícita la cláusula ORDER BY. Por ejemplo, si quieres enumerar a todos los cantantes en el orden de la clave primaria, usa esta consulta:

SELECT * FROM Singers
ORDER BY SingerId;

Spanner garantiza el orden de los resultados solo si la cláusula ORDER BY está presente en la consulta. En otras palabras, considera esta consulta sin ORDER BY:

SELECT * FROM Singers;

Spanner no garantiza que los resultados de esta consulta estén en el orden de la clave primaria. Además, el orden de los resultados puede cambiar en cualquier momento y no se garantiza que sea coherente de una invocación a otra. Si una consulta tiene una cláusula ORDER BY y Spanner usa un índice que proporciona el orden requerido, Spanner no ordena los datos de forma explícita. Por lo tanto, no te preocupes por el impacto en el rendimiento de incluir esta cláusula. Puedes verificar si se incluye una operación de ordenamiento explícito en la ejecución si observas el plan de consultas.

Usa STARTS_WITH en lugar de LIKE

Debido a que Spanner no evalúa los patrones LIKE con parámetros hasta el momento de ejecución, Spanner debe leer todas las filas y evaluarlas en función de la expresión LIKE para filtrar las filas que no coinciden.

Cuando un patrón LIKE tiene el formato foo% (por ejemplo, comienza con una cadena fija y termina con un solo porcentaje de comodín) y la columna está indexada, usa STARTS_WITH en lugar de LIKE. Esta opción permite que Spanner optimice de manera más eficaz el plan de ejecución de consultas.

No se recomienda lo siguiente:

GoogleSQL

SELECT a.AlbumTitle FROM Albums a
WHERE a.AlbumTitle LIKE @like_clause;

PostgreSQL

SELECT a.AlbumTitle FROM Albums a
WHERE a.AlbumTitle LIKE $1;

Se recomienda lo siguiente:

GoogleSQL

SELECT a.AlbumTitle FROM Albums a
WHERE STARTS_WITH(a.AlbumTitle, @prefix);

PostgreSQL

SELECT a.AlbumTitle FROM Albums a
WHERE STARTS_WITH(a.AlbumTitle, $2);

Usa marcas de tiempo de confirmación

Si tu aplicación necesita consultar datos escritos después de un momento determinado, agrega columnas de marcas de tiempo de confirmación a las tablas relevantes. Las marcas de tiempo de confirmación habilitan una optimización de Spanner que puede reducir la E/S de las consultas cuyas cláusulas WHERE restringen los resultados a las filas escritas más recientemente que una hora específica.

Obtén más información sobre esta optimización con bases de datos de dialecto de GoogleSQL o con bases de datos de dialectos de PostgreSQL.