¿Por qué hay más (y un número variable de) lecturas lógicas con lectura anticipada (captación previa)?

8

Después de crear la base de datos tpch en mi SQL Server, probé la siguiente consulta:

    set statistics io on
    DBCC DROPCLEANBUFFERS;        
    select top 100 * from dbo.lineitem order by l_partkey;

El elemento de línea de tabla tiene un índice no agrupado en l_partkey. Emití las consultas anteriores varias veces y descubrí que las lecturas lógicas varían cada vez:

    Table 'lineitem'. Scan count 1, logical reads 1019, physical reads 4, read-ahead reads 1760, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'lineitem'. Scan count 1, logical reads 1007, physical reads 4, read-ahead reads 1720, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.
    Table 'lineitem'. Scan count 1, logical reads 1030, physical reads 4, read-ahead reads 1792, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

De la publicación aquí: el recuento de lectura lógica varía , sé que podría deberse a un comportamiento de lectura anticipada.

¿PERO exactamente por qué leer con anticipación podría causar más lecturas lógicas? ¿Cómo cambia el comportamiento del servidor SQL? Al igual que SQL Server, ¿puede leer más páginas de índice ya que de todos modos está en caché?

De todos modos, deshabilité la lectura anticipada y emití la consulta anterior nuevamente. Ahora informa la misma cantidad de lecturas lógicas cada vez. ¡PERO las lecturas lógicas son mucho más pequeñas!

    Table 'lineitem'. Scan count 1, logical reads 404, physical reads 160, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Entonces mi pregunta es, ¿por qué la función de lectura anticipada podría causar muchas más y varias lecturas lógicas cuentan?

Por curiosidad, probé otra consulta sin el "ordenar por":

    select top 100 * from dbo.lineitem

Aquí está el resultado sin leer a continuación:

    Table 'lineitem'. Scan count 1, logical reads 5, physical reads 3, read-ahead reads 0, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

Aquí está el resultado con lectura anticipada:

    Table 'lineitem'. Scan count 1, logical reads 15, physical reads 2, read-ahead reads 3416, lob logical reads 0, lob physical reads 0, lob read-ahead reads 0.

El que tiene lectura anticipada aún tiene lecturas más lógicas. ¿Entonces por qué?

usuario3610199
fuente

Respuestas:

9

El plan de consulta para el ORDER BY l_partkeyejemplo casi seguro lee el índice no agrupado en orden (con lectura anticipada), seguido de una búsqueda clave para recuperar las columnas descubiertas.

El operador de unión de bucles anidados sobre la búsqueda probablemente utiliza prefetching adicional ( WithOrderedPrefetch) para la búsqueda. Vea el siguiente artículo que escribí para más detalles:

Además, como mencioné en respuesta a las preguntas y respuestas vinculadas, el número de lecturas de lectura anticipada depende de las características del subsistema de tiempo y almacenamiento. El mismo tipo de consideraciones se aplica a la captación previa de búsqueda en la unión de bucles anidados.

Tenga en cuenta que SQL Server emite lecturas anticipadas para las páginas que podrían ser necesarias para la exploración del índice, pero esto no está limitado por la TOPespecificación en la consulta. El TOPes un elemento de procesador de consultas, mientras que el motor de almacenamiento controla la lectura anticipada.

Las actividades están bastante separadas: la lectura anticipada (y la captación previa) emiten E / S asíncronas para las páginas que puede necesitar el Escaneo (o Búsqueda).

Dependiendo del orden en que las E / S se completan y ponen las filas a disposición del procesador de consultas (entre otras cosas), el número de páginas realmente tocadas (lecturas lógicas) o leídas físicamente puede variar. Tenga en cuenta en particular que la búsqueda previa retrasada de búsqueda también contribuye a las lecturas lógicas cuando verifica si una página necesaria para la búsqueda ya está en la memoria o no.

Por lo tanto, todo se reduce al momento detallado de las operaciones superpuestas: el procesador de consultas comenzará a cerrar la tubería de ejecución de consultas tan pronto como se haya visto el número requerido de filas (100) en el iterador superior. Cuántas E / S asíncronas (lectura anticipada o captación previa) se habrán emitido o completado en ese punto es esencialmente no determinista.

Puede deshabilitar la captación previa de bucles anidados con la marca de seguimiento 8744 para explorar esto más a fondo. Esto eliminará la WithOrderedPrefetchpropiedad de la unión de bucles anidados. Usualmente uso OPTION (QUERYTRACEON 8744)en la consulta en sí. En cualquier caso, debe asegurarse de no reutilizar un plan en caché que tenga la captación previa. Borre el caché del plan cada vez o fuerce una recompilación de consultas con OPTION (RECOMPILE).

Las lecturas lógicas son una medida simple del número de páginas de caché tocadas en nombre de la consulta. Cuando la lectura anticipada (y / o la captación previa) está habilitada, se pueden tocar más (¡y diferentes!) Páginas de índice y datos para emitir esa lectura anticipada o como parte de la actividad de captación previa.

Paul White 9
fuente