¿Las columnas no relevantes afectan el tiempo de consulta de las declaraciones de selección?

10

Tengo curiosidad.

Digamos que tiene una tabla de 1 millón de registros / filas.

select order_value from store.orders

¿Hace alguna diferencia si esa tabla tiene 1 campo, 2 campos o 100 campos, en el tiempo de consulta real? Me refiero a todos los campos que no sean "order_value".

En este momento estoy enviando datos a un almacén de datos. A veces vuelco campos en la tabla que "pueden usarse en el futuro, algún día", pero no están siendo consultados en este momento, por nada. ¿Estos campos 'extraños' afectarían las declaraciones de selección que no los incluyen, directa o indirectamente (no * quiero decir)?

usuario45867
fuente
Hay toneladas de información sobre esto disponible en la web. La clave es obtener la información más reciente a medida que la tecnología cambia. Lo que está preguntando depende tanto de su configuración particular que no es posible dar una muy buena respuesta. Un punto clave para recordar es que a medida que avanzamos hacia SSD, muchas cosas que alguna vez fueron muy importantes para el rendimiento ya no son el caso.
Joe

Respuestas:

10

Esto realmente depende de índices y tipos de datos.

Usando la base de datos Stack Overflow como ejemplo, así es como se ve la tabla Usuarios:

NUECES

Tiene un PK / CX en la columna Id. Entonces, es la totalidad de los datos de la tabla ordenados por Id.

Con eso como el único índice, SQL tiene que leer todo eso (sin las columnas LOB) en la memoria si aún no está allí.

DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.

SET STATISTICS TIME, IO ON 

SELECT u.Id
INTO  #crap1
FROM dbo.Users AS u

El tiempo de estadísticas y el perfil io se ve así:

Table 'Users'. Scan count 7, logical reads 80846, physical reads 0, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2406 ms,  elapsed time = 446 ms.

Si agrego un índice no agrupado adicional solo con Id

CREATE INDEX ix_whatever ON dbo.Users (Id)

Ahora tengo un índice mucho más pequeño que satisface mi consulta.

DBCC DROPCLEANBUFFERS-- Don't run this anywhere near prod.

SELECT u.Id
INTO  #crap2
FROM dbo.Users AS u

El perfil aquí:

Table 'Users'. Scan count 7, logical reads 6587, physical reads 0, read-ahead reads 6549, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

 SQL Server Execution Times:
   CPU time = 2344 ms,  elapsed time = 384 ms.

Podemos hacer muchas menos lecturas y ahorrar un poco de tiempo de CPU.

Sin más información sobre la definición de su tabla, realmente no puedo intentar reproducir mejor lo que está tratando de medir.

¿Pero está diciendo que a menos que haya un índice específico en esa columna solitaria, también se escanearán las otras columnas / campos? ¿Es esto solo un inconveniente inherente al diseño de las tablas del almacén de filas? ¿Por qué se escanearían los campos irrelevantes?

Sí, esto es específico para las tablas del almacén de filas. Los datos son almacenados por la fila en las páginas de datos. Incluso si otros datos en la página son irrelevantes para su consulta, toda la fila> página> índice debe leerse en la memoria. No diría que las otras columnas se "escanean" tanto como las páginas en las que existen se escanean para recuperar el valor único en ellas relevante para la consulta.

Usando el ejemplo de la antigua agenda: incluso si solo está leyendo los números de teléfono, cuando pasa la página, cambia el apellido, el nombre, la dirección, etc. junto con el número de teléfono.

Erik Darling
fuente
@ jpmc26 Puede ser peor que eso, porque si las columnas solicitadas son parte de un índice, la consulta se puede atender simplemente mirando el índice. Si las columnas no están indexadas, pueden hacer que se cargue el registro primario e incluso registros secundarios para tipos de tabla / columna no agrupados.
Christopher Schultz
12

Depende de la estructura de la tabla y de los índices disponibles.

  • Caso A: tabla común (almacén de filas), sin índice activado (order_value).

    El único plan de ejecución posible es leer toda la tabla (que, por supuesto, es muy diferente cuando se trata de 2 vs 200 columnas, por lo que unos pocos vs unos pocos miles de bytes de ancho).

  • Caso B: tabla común, hay un índice en (order_value)o algunos otros índices que incluyen esa columna.

    Ahora hay un mejor plan, escanear todo el índice (uno de ellos), que por supuesto es mucho más estrecho que toda la tabla, solo unos pocos bytes. Lo que hace irrelevante si la tabla tiene 2 o 200 columnas. Solo se escanea el índice.

  • Caso C: es una tabla de almacén de columnas.

    Como su nombre lo indica, la estructura de estas tablas está orientada por columnas, no por filas. No hay necesidad de ningún índice, el diseño de la tabla en sí es adecuado para leer columnas enteras.

ypercubeᵀᴹ
fuente
Mi conocimiento es un poco verde sobre este tema. Es más convencional (por ejemplo, la base de datos típica de SQL Server) tener tablas de almacén de filas, ¿correcto? ¿Por qué se escanearía toda la tabla si solo se necesita devolver una columna / campo? ¿Es esto inherente al diseño de las tablas del almacén de filas?
user45867
@ user45867 sí, los datos se almacenan en filas (excepto algunas columnas muy grandes que se almacenan afuera). Cuando SQL Server lee desde el disco, lee en bloques completos, no puede leer solo la parte que tiene una columna.
ypercubeᵀᴹ