Gestionar índices de búsqueda

Un índice de búsqueda es una estructura de datos diseñada para permitir búsquedas muy eficientes con la función SEARCH. Un índice de búsqueda también puede optimizar algunas consultas que usen funciones y operadores compatibles.

Al igual que el índice que se encuentra en la parte posterior de un libro, un índice de búsqueda de una columna de datos de cadena actúa como una tabla auxiliar que tiene una columna para palabras únicas y otra para indicar en qué parte de los datos aparecen esas palabras.

Crear un índice de búsqueda

Para crear un índice de búsqueda, usa la instrucción DDL CREATE SEARCH INDEX. Para especificar los tipos de datos primitivos que se van a indexar, consulta Crear un índice de búsqueda y especificar las columnas y los tipos de datos. Si no especificas ningún tipo de datos, BigQuery indexará de forma predeterminada las columnas de los siguientes tipos que contengan datos STRING:

  • STRING
  • ARRAY<STRING>
  • STRUCT que contenga al menos un campo anidado de tipo STRING o ARRAY<STRING>
  • JSON

Cuando creas un índice de búsqueda, puedes especificar el tipo de analizador de texto que quieres usar. El analizador de texto controla cómo se tokenizan los datos para la indexación y la búsqueda. El valor predeterminado es LOG_ANALYZER. Este analizador funciona bien con los registros generados por máquinas y tiene reglas especiales sobre los tokens que se suelen encontrar en los datos de observabilidad, como las direcciones IP o los correos electrónicos. Usa NO_OP_ANALYZER cuando tengas datos preprocesados que quieras que coincidan exactamente. PATTERN_ANALYZER extrae tokens de texto mediante una expresión regular.

Crear un índice de búsqueda con el analizador de texto predeterminado

En el ejemplo siguiente, se crea un índice de búsqueda en las columnas a y c de simple_table y se usa el analizador de texto LOG_ANALYZER de forma predeterminada:

CREATE TABLE dataset.simple_table(a STRING, b INT64, c JSON);

CREATE SEARCH INDEX my_index
ON dataset.simple_table(a, c);

Crear un índice de búsqueda en todas las columnas con el analizador NO_OP_ANALYZER

Cuando creas un índice de búsqueda en ALL COLUMNS, se indexan todos los datos de STRING o JSON de la tabla. Si la tabla no contiene datos de este tipo (por ejemplo, si todas las columnas contienen números enteros), no se podrá crear el índice. Cuando especifica una columna STRUCT para que se indexe, se indexan todos los subcampos anidados.

En el siguiente ejemplo, se crea un índice de búsqueda en a, c.e y c.f.g, y se usa el analizador de texto NO_OP_ANALYZER:

CREATE TABLE dataset.my_table(
  a STRING,
  b INT64,
  c STRUCT <d INT64,
            e ARRAY<STRING>,
            f STRUCT<g STRING, h INT64>>) AS
SELECT 'hello' AS a, 10 AS b, (20, ['x', 'y'], ('z', 30)) AS c;

CREATE SEARCH INDEX my_index
ON dataset.my_table(ALL COLUMNS)
OPTIONS (analyzer = 'NO_OP_ANALYZER');

Como el índice de búsqueda se creó el ALL COLUMNS, las columnas que se añadan a la tabla se indexarán automáticamente si contienen datos de STRING.

Crear un índice de búsqueda y especificar las columnas y los tipos de datos

Cuando creas un índice de búsqueda, puedes especificar los tipos de datos que quieres usar. Los tipos de datos controlan los tipos de columnas y subcampos de las columnas JSON y STRUCT para la indexación. El tipo de datos predeterminado para la indexación es STRING. Para crear un índice de búsqueda con más tipos de datos (por ejemplo, tipos numéricos), usa la instrucción CREATE SEARCH INDEX con la opción data_types incluida.

En el siguiente ejemplo, se crea un índice de búsqueda en las columnas a, b, c y d de una tabla llamada simple_table. Los tipos de datos de columna admitidos son STRING, INT64 y TIMESTAMP.

CREATE TABLE dataset.simple_table(a STRING, b INT64, c JSON, d TIMESTAMP);

CREATE SEARCH INDEX my_index
ON dataset.simple_table(a, b, c, d)
OPTIONS ( data_types = ['STRING', 'INT64', 'TIMESTAMP']);

Crea un índice de búsqueda en todas las columnas y especifica los tipos de datos

Cuando creas un índice de búsqueda en ALL COLUMNS con la opción data_types especificada, se indexa cualquier columna que coincida con uno de los tipos de datos especificados. En las columnas JSON y STRUCT, se indexa cualquier subcampo anidado que coincida con uno de los tipos de datos especificados.

En el siguiente ejemplo, se crea un índice de búsqueda en ALL COLUMNS con tipos de datos especificados. Se indexan las columnas a, b, c, d.e, d.f, d.g.h y d.g.i de una tabla llamada my_table:

CREATE TABLE dataset.my_table(
  a STRING,
  b INT64,
  c TIMESTAMP,
  d STRUCT <e INT64,
            f ARRAY<STRING>,
            g STRUCT<h STRING, i INT64>>)
AS (
  SELECT
    'hello' AS a,
    10 AS b,
    TIMESTAMP('2008-12-25 15:30:00 UTC') AS c,
    (20, ['x', 'y'], ('z', 30)) AS d;
)

CREATE SEARCH INDEX my_index
ON dataset.my_table(ALL COLUMNS)
OPTIONS ( data_types = ['STRING', 'INT64', 'TIMESTAMP']);

Como el índice de búsqueda se creó el ALL COLUMNS, las columnas que se añadan a la tabla se indexarán automáticamente si coinciden con alguno de los tipos de datos especificados.

Índice con granularidad de columna

Cuando creas un índice de búsqueda, puedes especificar la granularidad de la columna de una columna indexada. La granularidad de las columnas permite a BigQuery optimizar ciertos tipos de consultas de búsqueda almacenando información adicional de las columnas en tu índice de búsqueda. Para definir la granularidad de las columnas indexadas, usa la opción index_granularity en index_column_option_list al ejecutar una declaración CREATE SEARCH INDEX.

Internamente, las tablas de BigQuery se organizan en archivos. Cuando creas un índice, BigQuery crea una asignación de tokens a los archivos que contienen esos tokens. Cuando ejecutas una consulta de búsqueda, BigQuery analiza todos los archivos que contienen los tokens. Esto puede ser ineficiente si el token de búsqueda rara vez aparece en la columna que estás buscando, pero es habitual en otra columna.

Por ejemplo, supongamos que tiene la siguiente tabla con ofertas de empleo:

CREATE TABLE my_dataset.job_postings (job_id INT64, company_name STRING, job_description STRING);

La palabra habilidades probablemente aparezca con frecuencia en la columna job_description, pero rara vez en la columna company_name. Supongamos que ejecutas la siguiente consulta:

SELECT * FROM my_dataset.job_postings WHERE SEARCH(company_name, 'skills');

Si has creado un índice de búsqueda en las columnas company_name y job_description sin especificar la granularidad de las columnas, BigQuery analizará todos los archivos en los que aparezca la palabra habilidades en la columna job_description o en la company_name. Para mejorar el rendimiento de esta consulta, puedes definir la granularidad de la columna company_name en COLUMN:

CREATE SEARCH INDEX my_index
ON my_dataset.job_postings (
  company_name OPTIONS(index_granularity = 'COLUMN'),
  job_description);

Ahora, cuando ejecutes la consulta, BigQuery solo analizará los archivos en los que la palabra skills aparezca en la columna company_name.

Para ver información sobre las opciones que se han definido en las columnas de una tabla indexada, consulta la vista INFORMATION_SCHEMA.SEARCH_INDEX_COLUMN_OPTIONS.

Hay límites en el número de columnas que puedes indexar con la granularidad de columna. Para obtener más información, consulta Cuotas y límites.

Información sobre la actualización del índice

BigQuery gestiona por completo los índices de búsqueda y los actualiza automáticamente cuando cambia la tabla. Se puede producir una actualización completa de un índice en los siguientes casos:

  • Se ha actualizado el vencimiento de la partición.
  • Se actualiza una columna indexada debido a un cambio en el esquema de la tabla.
  • El índice está obsoleto porque no hay BACKGROUND espacios de reserva para las actualizaciones incrementales. Para evitar que se produzcan retrasos, puedes usar el autoescalado y monitorizar la carga de trabajo para determinar el mejor valor de referencia y el tamaño máximo de la reserva.

Si los datos de una columna indexada se actualizan en todas las filas, como durante una operación de relleno, se debe actualizar todo el índice, lo que equivale a una actualización completa. Te recomendamos que realices los rellenos lentamente, por ejemplo, por partición, para minimizar el posible impacto negativo.

Si haces algún cambio en el esquema de la tabla base que impida que se indexe una columna indexada explícitamente, el índice se inhabilitará de forma permanente.

Si elimina la única columna indexada de una tabla o cambia el nombre de la tabla, el índice de búsqueda se elimina automáticamente.

Los índices de búsqueda se han diseñado para tablas grandes. Si crea un índice de búsqueda en una tabla que tiene un tamaño inferior a 10 GB, el índice no se rellenará. Del mismo modo, si elimina datos de una tabla indexada y el tamaño de la tabla es inferior a 10 GB, el índice se inhabilitará temporalmente. En este caso, las consultas de búsqueda no usan el índice y el código IndexUnusedReason es BASE_TABLE_TOO_SMALL. Esto ocurre tanto si usas tu propia reserva para tus trabajos de gestión de índices como si no. Cuando el tamaño de una tabla indexada supera los 10 GB, su índice se rellena automáticamente. No se te cobrará por el almacenamiento hasta que el índice de búsqueda se rellene y esté activo. Las consultas que usan la SEARCHfunción siempre devuelven resultados correctos, aunque algunos datos aún no se hayan indexado.

Obtener información sobre los índices de búsqueda

Para verificar la existencia y la disponibilidad de un índice de búsqueda, consulta INFORMATION_SCHEMA. Hay tres vistas que contienen metadatos sobre los índices de búsqueda.

INFORMATION_SCHEMA.SEARCH_INDEXES ver ejemplos

En esta sección se incluyen ejemplos de consultas de la vista INFORMATION_SCHEMA.SEARCH_INDEXES.

En el siguiente ejemplo se muestran todos los índices de búsqueda activos de las tablas del conjunto de datos my_dataset, ubicado en el proyecto my_project. Incluye sus nombres, las instrucciones DDL usadas para crearlos, su porcentaje de cobertura y su analizador de texto. Si una tabla base indexada tiene menos de 10 GB, su índice no se rellena, en cuyo caso coverage_percentage es 0.

SELECT table_name, index_name, ddl, coverage_percentage, analyzer
FROM my_project.my_dataset.INFORMATION_SCHEMA.SEARCH_INDEXES
WHERE index_status = 'ACTIVE';

Los resultados deberían tener este aspecto:

+-------------+-------------+--------------------------------------------------------------------------------------+---------------------+----------------+
| table_name  | index_name  | ddl                                                                                  | coverage_percentage | analyzer       |
+-------------+-------------+--------------------------------------------------------------------------------------+---------------------+----------------+
| small_table | names_index | CREATE SEARCH INDEX `names_index` ON `my_project.my_dataset.small_table`(names)      | 0                   | NO_OP_ANALYZER |
| large_table | logs_index  | CREATE SEARCH INDEX `logs_index` ON `my_project.my_dataset.large_table`(ALL COLUMNS) | 100                 | LOG_ANALYZER   |
+-------------+-------------+--------------------------------------------------------------------------------------+---------------------+----------------+

INFORMATION_SCHEMA.SEARCH_INDEX_COLUMNS ver ejemplos

En esta sección se incluyen ejemplos de consultas de la vista INFORMATION_SCHEMA.SEARCH_INDEX_COLUMNS.

En el siguiente ejemplo se crea un índice de búsqueda en todas las columnas de my_table.

CREATE TABLE dataset.my_table(
  a STRING,
  b INT64,
  c STRUCT <d INT64,
            e ARRAY<STRING>,
            f STRUCT<g STRING, h INT64>>) AS
SELECT 'hello' AS a, 10 AS b, (20, ['x', 'y'], ('z', 30)) AS c;

CREATE SEARCH INDEX my_index
ON dataset.my_table(ALL COLUMNS);

La siguiente consulta extrae información sobre los campos indexados. El símbolo index_field_path indica qué campo de una columna está indexado. Se diferencia de index_column_name solo en el caso de STRUCT, donde se indica la ruta completa al campo indexado. En este ejemplo, la columna c contiene un campo ARRAY<STRING> e y otro STRUCT llamado f, que contiene un campo STRING g. Cada uno de estos campos está indexado.

SELECT table_name, index_name, index_column_name, index_field_path
FROM my_project.dataset.INFORMATION_SCHEMA.SEARCH_INDEX_COLUMNS

El resultado es similar al siguiente:

+------------+------------+-------------------+------------------+
| table_name | index_name | index_column_name | index_field_path |
+------------+------------+-------------------+------------------+
| my_table   | my_index   | a                 | a                |
| my_table   | my_index   | c                 | c.e              |
| my_table   | my_index   | c                 | c.f.g            |
+------------+------------+-------------------+------------------+

La siguiente consulta une la vista INFORMATION_SCHEMA.SEARCH_INDEX_COUMNS con las vistas INFORMATION_SCHEMA.SEARCH_INDEXES y INFORMATION_SCHEMA.COLUMNS para incluir el estado del índice de búsqueda y el tipo de datos de cada columna:

SELECT
  index_columns_view.index_catalog AS project_name,
  index_columns_view.index_SCHEMA AS dataset_name,
  indexes_view.TABLE_NAME AS table_name,
  indexes_view.INDEX_NAME AS index_name,
  indexes_view.INDEX_STATUS AS status,
  index_columns_view.INDEX_COLUMN_NAME AS column_name,
  index_columns_view.INDEX_FIELD_PATH AS field_path,
  columns_view.DATA_TYPE AS data_type
FROM
  mydataset.INFORMATION_SCHEMA.SEARCH_INDEXES indexes_view
INNER JOIN
  mydataset.INFORMATION_SCHEMA.SEARCH_INDEX_COLUMNS index_columns_view
  ON
    indexes_view.TABLE_NAME = index_columns_view.TABLE_NAME
    AND indexes_view.INDEX_NAME = index_columns_view.INDEX_NAME
LEFT OUTER JOIN
  mydataset.INFORMATION_SCHEMA.COLUMNS columns_view
  ON
    indexes_view.INDEX_CATALOG = columns_view.TABLE_CATALOG
    AND indexes_view.INDEX_SCHEMA = columns_view.TABLE_SCHEMA
    AND index_columns_view.TABLE_NAME = columns_view.TABLE_NAME
    AND index_columns_view.INDEX_COLUMN_NAME = columns_view.COLUMN_NAME
ORDER BY
  project_name,
  dataset_name,
  table_name,
  column_name;

El resultado es similar al siguiente:

+------------+------------+----------+------------+--------+-------------+------------+---------------------------------------------------------------+
| project    | dataset    | table    | index_name | status | column_name | field_path | data_type                                                     |
+------------+------------+----------+------------+--------+-------------+------------+---------------------------------------------------------------+
| my_project | my_dataset | my_table | my_index   | ACTIVE | a           | a          | STRING                                                        |
| my_project | my_dataset | my_table | my_index   | ACTIVE | c           | c.e        | STRUCT<d INT64, e ARRAY<STRING>, f STRUCT<g STRING, h INT64>> |
| my_project | my_dataset | my_table | my_index   | ACTIVE | c           | c.f.g      | STRUCT<d INT64, e ARRAY<STRING>, f STRUCT<g STRING, h INT64>> |
+------------+------------+----------+------------+--------+-------------+------------+---------------------------------------------------------------+

INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION ver ejemplos

En esta sección se incluyen ejemplos de consultas de la vista INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION.

Comprobar si el consumo supera el límite en una región determinada

En el siguiente ejemplo se muestra qué ocurre si el tamaño total de la tabla base indexada de una organización que utiliza slots compartidos en la multirregión de EE. UU. supera los 100 TB:

WITH
 indexed_base_table_size AS (
 SELECT
   SUM(base_table.total_logical_bytes) AS total_logical_bytes
 FROM
   `region-us`.INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION AS search_index
 JOIN
   `region-us`.INFORMATION_SCHEMA.TABLE_STORAGE_BY_ORGANIZATION AS base_table
 ON
   (search_index.table_name = base_table.table_name
     AND search_index.project_id = base_table.project_id
     AND search_index.index_schema = base_table.table_schema)
 WHERE
   TRUE
   -- Excludes search indexes that are permanently disabled.
   AND search_index.index_status != 'PERMANENTLY DISABLED'
   -- Excludes BASE_TABLE_TOO_SMALL search indexes whose base table size is
   -- less than 10 GB. These tables don't count toward the limit.
   AND search_index.index_status_details.throttle_status != 'BASE_TABLE_TOO_SMALL'
   -- Excludes search indexes whose project has BACKGROUND reservation purchased
   -- for search indexes.
   AND search_index.use_background_reservation = false
 -- Outputs the total indexed base table size if it exceeds 100 TB,
 -- otherwise, doesn't return any output.
)
SELECT * FROM indexed_base_table_size
WHERE total_logical_bytes >= 109951162777600 -- 100 TB

El resultado es similar al siguiente:

+---------------------+
| total_logical_bytes |
+---------------------+
|     109951162777601 |
+---------------------+

Buscar el tamaño total de la tabla base indexada por proyectos en una región

En el siguiente ejemplo se muestra el desglose de cada proyecto de una multirregión de EE. UU. con el tamaño total de las tablas base indexadas:

SELECT
 search_index.project_id,
 search_index.use_background_reservation,
 SUM(base_table.total_logical_bytes) AS total_logical_bytes
FROM
 `region-us`.INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION AS search_index
JOIN
 `region-us`.INFORMATION_SCHEMA.TABLE_STORAGE_BY_ORGANIZATION AS base_table
ON
 (search_index.table_name = base_table.table_name
   AND search_index.project_id = base_table.project_id
   AND search_index.index_schema = base_table.table_schema)
WHERE
 TRUE
  -- Excludes search indexes that are permanently disabled.
  AND search_index.index_status != 'PERMANENTLY DISABLED'
  -- Excludes BASE_TABLE_TOO_SMALL search indexes whose base table size is
  -- less than 10 GB. These tables don't count toward limit.
 AND search_index.index_status_details.throttle_status != 'BASE_TABLE_TOO_SMALL'
GROUP BY search_index.project_id, search_index.use_background_reservation

El resultado es similar al siguiente:

+---------------------+----------------------------+---------------------+
|     project_id      | use_background_reservation | total_logical_bytes |
+---------------------+----------------------------+---------------------+
| projecta            |     true                   |     971329178274633 |
+---------------------+----------------------------+---------------------+
| projectb            |     false                  |     834638211024843 |
+---------------------+----------------------------+---------------------+
| projectc            |     false                  |     562910385625126 |
+---------------------+----------------------------+---------------------+

Buscar índices de búsqueda limitados

En el siguiente ejemplo se devuelven todos los índices de búsqueda que tienen limitaciones de frecuencia en la organización y la región:

SELECT project_id, index_schema, table_name, index_name
FROM
 `region-us`.INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION
WHERE
 -- Excludes search indexes that are permanently disabled.
 index_status != 'PERMANENTLY DISABLED'
 AND index_status_details.throttle_status IN ('ORGANIZATION_LIMIT_EXCEEDED', 'BASE_TABLE_TOO_LARGE')

El resultado es similar al siguiente:

+--------------------+--------------------+---------------+----------------+
|     project_id     |    index_schema    |  table_name   |   index_name   |
+--------------------+--------------------+---------------+----------------+
|     projecta       |     dataset_us     |   table1      |    index1      |
|     projectb       |     dataset_us     |   table1      |    index1      |
+--------------------+--------------------+---------------+----------------+

Opciones de gestión de índices

Para crear índices y que BigQuery los mantenga, tienes dos opciones:

Usar slots compartidos

Si no has configurado tu proyecto para que use una reserva dedicada para la indexación, la gestión de índices se realiza en el grupo de ranuras compartido gratuito, sujeto a las siguientes restricciones.

Si añades datos a una tabla que provoca que el tamaño total de las tablas indexadas supere el límite de tu organización, BigQuery pausará la gestión de índices de esa tabla. Cuando esto ocurre, el campo index_status de la vista INFORMATION_SCHEMA.SEARCH_INDEXES muestra PENDING DISABLEMENT y el índice se pone en cola para su eliminación. Mientras el índice está pendiente de inhabilitación, se sigue usando en las consultas y se te cobra por el almacenamiento del índice. Una vez que se elimina el índice, el campo index_status muestra el índice como TEMPORARILY DISABLED. En este estado, las consultas no usan el índice y no se te cobra por el almacenamiento del índice. En este caso, el código IndexUnusedReason es BASE_TABLE_TOO_LARGE.

Si elimina datos de la tabla y el tamaño total de las tablas indexadas es inferior al límite por organización, se reanudará la gestión de índices. El campo index_status de la vista INFORMATION_SCHEMA.SEARCH_INDEXES es ACTIVE, las consultas pueden usar el índice y se te cobra por el almacenamiento del índice.

Puedes usar la vista INFORMATION_SCHEMA.SEARCH_INDEXES_BY_ORGANIZATION para ver el consumo actual en relación con el límite por organización de una región concreta, desglosado por proyectos y tablas.

BigQuery no garantiza la disponibilidad del grupo compartido ni el rendimiento de la indexación que veas. En el caso de las aplicaciones de producción, puede que te interese usar ranuras específicas para procesar los índices.

Usar tu propia reserva

En lugar de usar el grupo de ranuras compartido predeterminado, puedes designar tu propia reserva para indexar tus tablas. Si usas tu propia reserva, te aseguras de que las tareas de gestión de índices, como la creación, la actualización y las optimizaciones en segundo plano, tengan un rendimiento predecible y constante.

  • No hay límites de tamaño de tabla cuando se ejecuta un trabajo de indexación en tu reserva.
  • Usar tu propia reserva te ofrece flexibilidad en la gestión de índices. Si necesitas crear un índice muy grande o hacer una actualización importante en una tabla indexada, puedes añadir temporalmente más ranuras a la asignación.

Para indexar las tablas de un proyecto con una reserva designada, crea una reserva en la región en la que se encuentren tus tablas. A continuación, asigna el proyecto a la reserva con el valor job_type definido como BACKGROUND:

SQL

Usa la CREATE ASSIGNMENT instrucción DDL.

  1. En la Google Cloud consola, ve a la página BigQuery.

    Ir a BigQuery

  2. En el editor de consultas, introduce la siguiente instrucción:

    CREATE ASSIGNMENT
      `ADMIN_PROJECT_ID.region-LOCATION.RESERVATION_NAME.ASSIGNMENT_ID`
    OPTIONS (
      assignee = 'projects/PROJECT_ID',
      job_type = 'BACKGROUND');

    Haz los cambios siguientes:

    • ADMIN_PROJECT_ID: el ID de proyecto del proyecto de administración que posee el recurso de reserva
    • LOCATION: la ubicación de la reserva
    • RESERVATION_NAME: el nombre de la reserva
    • ASSIGNMENT_ID: el ID de la tarea

      El ID debe ser único para el proyecto y la ubicación, empezar y terminar con una letra minúscula o un número, y contener solo letras minúsculas, números y guiones.

    • PROJECT_ID: el ID del proyecto que contiene las tablas que se van a indexar. Este proyecto está asignado a la reserva.

  3. Haz clic en Ejecutar.

Para obtener más información sobre cómo ejecutar consultas, consulta Ejecutar una consulta interactiva.

bq

Usa el comando bq mk:

bq mk \
    --project_id=ADMIN_PROJECT_ID \
    --location=LOCATION \
    --reservation_assignment \
    --reservation_id=RESERVATION_NAME \
    --assignee_id=PROJECT_ID \
    --job_type=BACKGROUND \
    --assignee_type=PROJECT

Haz los cambios siguientes:

  • ADMIN_PROJECT_ID: el ID del proyecto de administración que tiene el recurso de reserva.
  • LOCATION: la ubicación de la reserva
  • RESERVATION_NAME: el nombre de la reserva
  • PROJECT_ID: ID del proyecto que se va a asignar a esta reserva

Ver tus tareas de indexación

Se crea un nuevo trabajo de indexación cada vez que se crea o se actualiza un índice en una sola tabla. Para ver información sobre el trabajo, consulta las vistas INFORMATION_SCHEMA.JOBS*. Puedes filtrar los trabajos de indexación configurando job_type IS NULL AND SEARCH(job_id, '`search_index`') en la cláusula WHERE de tu consulta. En el siguiente ejemplo se muestran los cinco trabajos de indexación más recientes del proyecto my_project:

SELECT *
FROM
 region-us.INFORMATION_SCHEMA.JOBS
WHERE
  project_id  = 'my_project'
  AND job_type IS NULL
  AND SEARCH(job_id, '`search_index`')
ORDER BY
 creation_time DESC
LIMIT 5;

Elige el tamaño de tu reserva

Para elegir el número de ranuras adecuado para tu reserva, debes tener en cuenta cuándo se ejecutan los trabajos de gestión de índices, cuántas ranuras utilizan y cómo es tu uso a lo largo del tiempo. BigQuery activa una tarea de gestión de índices en las siguientes situaciones:

  • Crea un índice en una tabla.
  • Los datos se modifican en una tabla indexada.
  • El esquema de una tabla cambia y esto afecta a las columnas que se indexan.
  • Los datos y los metadatos del índice se optimizan o actualizan periódicamente.

El número de ranuras que necesitas para un trabajo de gestión de índices en una tabla depende de los siguientes factores:

  • El tamaño de la tabla
  • La velocidad de ingestión de datos en la tabla
  • La frecuencia de las instrucciones DML aplicadas a la tabla
  • El retraso aceptable para crear y mantener el índice
  • La complejidad del índice, que suele determinarse por los atributos de los datos, como el número de términos duplicados
Estimación inicial

Las siguientes estimaciones pueden ayudarte a calcular cuántos slots requiere tu reserva. Debido a la naturaleza altamente variable de las cargas de trabajo de indexación, debes volver a evaluar tus requisitos después de empezar a indexar datos.

  • Datos actuales: con una reserva de 1000 ranuras, se puede indexar una tabla de BigQuery a una velocidad media de hasta 4 GiB por segundo, lo que equivale a unos 336 TiB al día.
  • Datos recién ingeridos: la indexación suele requerir más recursos en los datos recién ingeridos, ya que la tabla y su índice se someten a varias rondas de optimizaciones transformativas. De media, la indexación de datos recién ingeridos consume tres veces más recursos que la indexación inicial de los mismos datos.
  • Datos que se modifican con poca frecuencia: las tablas indexadas con pocos datos o sin datos que se modifiquen necesitan muchos menos recursos para mantener el índice. Se recomienda empezar con 1/5 de los slots necesarios para la indexación inicial de los mismos datos y no menos de 250 slots.
  • El progreso de la indexación se escala de forma aproximadamente lineal con el tamaño de la reserva. Sin embargo, no recomendamos usar reservas de menos de 250 espacios para la indexación, ya que podría provocar ineficiencias que ralenticen el proceso de indexación.
  • Estas estimaciones pueden cambiar a medida que varían las funciones, las optimizaciones y tu uso real.
  • Si el tamaño total de las tablas de tu organización supera el límite de indexación de tu región, debes mantener una reserva distinta de cero asignada a la indexación. De lo contrario, la indexación podría volver al nivel predeterminado, lo que provocaría la eliminación accidental de todos los índices.
Monitorizar el uso y el progreso

La mejor forma de evaluar el número de ranuras que necesitas para ejecutar de forma eficiente tus trabajos de gestión de índices es monitorizar la utilización de ranuras y ajustar el tamaño de la reserva en consecuencia. La siguiente consulta genera el uso diario de ranuras de las tareas de gestión de índices. En la región us-west1solo se incluyen los últimos 30 días:

SELECT
  TIMESTAMP_TRUNC(job.creation_time, DAY) AS usage_date,
  -- Aggregate total_slots_ms used for index-management jobs in a day and divide
  -- by the number of milliseconds in a day. This value is most accurate for
  -- days with consistent slot usage.
  SAFE_DIVIDE(SUM(job.total_slot_ms), (1000 * 60 * 60 * 24)) AS average_daily_slot_usage
FROM
  `region-us-west1`.INFORMATION_SCHEMA.JOBS job
WHERE
  project_id = 'my_project'
  AND job_type IS NULL
  AND SEARCH(job_id, '`search_index`')
GROUP BY
  usage_date
ORDER BY
  usage_date DESC
limit 30;

Si no hay suficientes ranuras para ejecutar trabajos de gestión de índices, un índice puede dejar de estar sincronizado con su tabla y los trabajos de indexación pueden fallar. En este caso, BigQuery vuelve a compilar el índice desde cero. Para evitar que el índice se desincronice, asegúrate de tener suficientes ranuras para admitir las actualizaciones del índice procedentes de la ingestión y la optimización de datos. Para obtener más información sobre cómo monitorizar el uso de las ranuras, consulta los gráficos de recursos de administrador.

Prácticas recomendadas

  • Los índices de búsqueda se han diseñado para tablas grandes. Las mejoras de rendimiento de un índice de búsqueda aumentan con el tamaño de la tabla.
  • No indexe columnas que contengan un número muy reducido de valores únicos.
  • No indexe las columnas que no vaya a usar nunca con la función SEARCH ni con ninguna de las otras funciones y operadores admitidos.
  • Ten cuidado al crear un índice de búsqueda en ALL COLUMNS. Cada vez que añadas una columna que contenga datos STRING o JSON, se indexará.
  • Debe usar su propia reserva para gestionar los índices en las aplicaciones de producción. Si decides usar el grupo de ranuras compartidas predeterminado para tus tareas de gestión de índices, se aplicarán los límites de tamaño por organización.

Eliminar un índice de búsqueda

Cuando ya no necesites un índice de búsqueda o quieras cambiar las columnas indexadas de una tabla, puedes eliminar el índice de esa tabla. Usa la DROP SEARCH INDEX instrucción DDL.

Si se elimina una tabla indexada, su índice se elimina automáticamente.

Ejemplo:

DROP SEARCH INDEX my_index ON dataset.simple_table;

Siguientes pasos

  • Para obtener una descripción general de los casos prácticos, los precios, los permisos necesarios y las limitaciones de los índices de búsqueda, consulta la introducción a la búsqueda en BigQuery.
  • Para obtener información sobre cómo buscar de forma eficiente en columnas indexadas, consulta Buscar con un índice.