¿Qué puede acelerar una consulta de conteo SQL?

9

Al hacer una consulta SQL de conteo (agregado), ¿qué puede acelerar el tiempo de ejecución en estos 3 sistemas de bases de datos? Estoy seguro de que muchas cosas podrían acelerarlo (hardware para uno), pero solo soy un DBA novato, así que estoy seguro de que obtendré algunas respuestas aquí. Migré alrededor de 157 millones de filas a una base de datos de SQL Server, y esta consulta lleva una eternidad. Pero en mi base de datos Netezza de origen, lleva segundos.

Por ejemplo:

Netezza 6:

SELECT COUNT(*) FROM DATABASENAME..MYTABLE

Oracle 11g:

SELECT COUNT(*) FROM MYTABLE

SQL Server 2012:

SELECT COUNT(*) FROM DATABASENAME.[dbo].[MYTABLE]
MacGyver
fuente
1
¿Necesita hacer esto solo una vez o repetidamente?
Jon Seigel
@JonSeigel estamos haciendo cargas incrementales, y estamos comparando registros entre sistemas de bases de datos cada día para asegurarnos de que los recuentos se sumen. Tan repetidamente
MacGyver

Respuestas:

10

Netezza es un dispositivo que está diseñado para sobresalir en escaneos de tablas grandes, por eso está obteniendo resultados tan rápidos en ese sistema.

Para su SQL Server, puede acelerar enormemente el recuento de filas consultando desde el DMV sys.dm_db_partition_stats.

SELECT s.name AS [Schema], o.name AS [Table], SUM(p.row_count) AS [RowCount]
FROM sys.dm_db_partition_stats p JOIN sys.objects o
ON p.object_id = o.object_id JOIN sys.schemas s
ON o.schema_id = s.schema_id
WHERE p.index_id < 2
AND o.object_id = object_id('MyTable')
GROUP BY o.name, s.name;

En un entorno de alta transacción, no se garantiza que este DMV sea 100% exacto. Pero a partir de su pregunta, parece que solo está haciendo recuentos de filas para verificar cada tabla después de su migración, por lo que esta consulta debería funcionar para usted.

Patrick Keisler
fuente
44
@ Phil ¿por qué? Si recorre las tablas y realiza un costoso SELECT COUNT (*) de cada una, ¿qué tan preciso es el primer resultado una vez que haya alcanzado la última tabla?
Aaron Bertrand
1
Para mayor claridad, Phil había dicho: "Usar el diccionario de datos, que no proporciona resultados 100% precisos, es un mal consejo. En mi opinión, la respuesta debe editarse para eliminar la sugerencia o eliminarse: recuerde que las personas buscan esas respuestas en Google y lo harán a ciegas cortar y pegar ... "Estoy de acuerdo en que el descargo de responsabilidad es importante (y supuestamente hay algunos casos extremos en los que los metadatos no arrojan resultados razonables), no estoy de acuerdo en que usar las vistas de metadatos en general sea un mal consejo.
Aaron Bertrand
5

Aquí hay una solución de SQL Server que utiliza COUNT_BIGdentro de una vista indizada. Esto le proporcionará un recuento coherente desde el punto de vista transaccional sin la sobrecarga de escaneos de tablas o índices grandes, y sin la necesidad del almacenamiento requerido para este último:

CREATE TABLE [dbo].[MyTable](id int);
GO

CREATE VIEW [dbo].[MyTableRowCount]
    WITH SCHEMABINDING
AS

    SELECT
        COUNT_BIG(*) AS TableRowCount
        FROM [dbo].[MyTable];
GO

CREATE UNIQUE CLUSTERED INDEX IX_MyTableRowCount
    ON [dbo].[MyTableRowCount](TableRowCount);
GO

SELECT
    TableRowCount
    FROM [dbo].[MyTableRowCount] WITH(NOEXPAND);

Esto requerirá un solo escaneo inicial (sin alejarse de esto) y agregará un poco de sobrecarga a las manipulaciones de datos de tabla incrementales. Si está realizando grandes operaciones con muchos datos (a diferencia de muchas operaciones pequeñas), creo que la sobrecarga en los cambios debería ser insignificante.

Jon Seigel
fuente
@SQLKiwi: ¿Cómo es que las lecturas están bloqueadas antes de 2012? Error del servidor SQL?
Jon Seigel
@ JonSeigel - Mis $ 0,05: los índices agrupados normales en la tabla normal creada sin conexión aplican un bloqueo Sch-M en la tabla. En una vista, por supuesto, no es necesario, pero esto significa una alteración en la operación Crear índice para crear un caso especial para la vista indizada, que se realizó para SQL2012. En mi humilde opinión, por supuesto.
Fabricio Araujo
3

En Oracle, un índice de árbol binario en una columna NOT NULL puede usarse para responder un COUNT (*). Será más rápido en la mayoría de los casos que un ESCANEO DE TABLA COMPLETA porque los índices suelen ser más pequeños que su tabla base.

Sin embargo, un índice de árbol binario regular seguirá siendo enorme con 157 Mrows. Si su tabla no se actualiza simultáneamente (es decir, solo el proceso de carga por lotes), es posible que desee utilizar un índice de mapa de bits en su lugar.

El índice de mapa de bits más pequeño sería algo como esto:

CREATE BITMAP INDEX ix ON your_table(NULL);

Las entradas nulas se tienen en cuenta por un índice de mapa de bits. El índice resultante será pequeño (20-30 bloques de 8k por millón de filas) en comparación con un índice de árbol binario regular o la tabla base.

El plan resultante debe mostrar las siguientes operaciones:

----------------------------------------------
| Id  | Operation                     | Name | 
----------------------------------------------
|   0 | SELECT STATEMENT              |      |
|   1 |  SORT AGGREGATE               |      |
|   2 |   BITMAP CONVERSION COUNT     |      |
|   3 |    BITMAP INDEX FAST FULL SCAN| IX   |
----------------------------------------------

Si su tabla se actualiza simultáneamente, un índice de mapa de bits con un valor único será un punto de contención y no debe usarse.

Vincent Malgrat
fuente
3

En Oracle, la consulta de conteo simple a menudo se ejecuta escaneando un índice en lugar de toda la tabla. El índice debe ser un índice de mapa de bits o definido en una columna con la restricción NOT NULL. Para consultas más complejas que requieren un escaneo completo de la tabla, puede usar consultas paralelas.

Para habilitar la consulta paralela (se requiere Enterprise Edition), puede usar la sugerencia de optimizador:

select /*+ PARALLEL(mytable, 12) */ count(*) from mytable;

O habilite la consulta paralela para todas las consultas en la tabla:

alter table mytable parallel 12;
sjk
fuente