Por que mais (e número variável de) leituras lógicas com leitura antecipada (pré-busca)?

8

Depois de criar o banco de dados tpch no meu SQL Server, tentei a consulta abaixo:

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

O item de linha da tabela possui um índice não agrupado em l_partkey. Emiti as consultas acima várias vezes e descobri que as leituras lógicas variam a 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.

Da postagem aqui: A contagem de leitura lógica varia , eu sei que isso pode ser causado pelo comportamento de leitura antecipada.

MAS exatamente por que ler com antecedência pode causar leituras mais lógicas? Como isso altera o comportamento do SQL Server? Como o SQL Server pode ler mais página de índice, pois está em cache, afinal?

De qualquer forma, desabilitei a leitura antecipada e emita a consulta acima novamente. Agora ele relata a mesma quantidade de leituras lógicas a cada vez. MAS as leituras lógicas são muito menores !!

    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.

Portanto, minha pergunta é: por que o recurso de leitura antecipada pode causar muito mais e várias leituras lógicas contam?

Por curiosidade, tentei outra consulta sem o "ordenar por":

    select top 100 * from dbo.lineitem

Aqui está o resultado sem ler adiante:

    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.

Aqui está o resultado com a leitura adiante:

    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.

Aquele com leitura à frente ainda tem leituras mais lógicas. Então por que?

user3610199
fonte

Respostas:

9

O plano de consulta para o ORDER BY l_partkeyexemplo quase certamente lê o índice não clusterizado em ordem (com leitura antecipada), seguido por uma pesquisa de chave para recuperar as colunas descobertas.

O operador Junção de loops aninhados acima da pesquisa provavelmente usa pré-busca adicional ( WithOrderedPrefetch) para a pesquisa. Consulte o seguinte artigo que escrevi para obter detalhes completos:

Além disso, como mencionei em resposta às perguntas e respostas vinculadas, o número de leituras de leitura antecipada depende das características do tempo e do subsistema de armazenamento. O mesmo tipo de consideração se aplica à pré-busca de pesquisa na associação de loops aninhados.

Observe que o SQL Server emite leitura antecipada para páginas que podem ser necessárias pela verificação do índice, mas isso não é limitado pela TOPespecificação na consulta. O TOPé um elemento do processador de consultas, enquanto a leitura antecipada é controlada pelo Mecanismo de Armazenamento.

As atividades são bastante separadas: a leitura antecipada (e a pré-busca) emitem E / S assíncrona para páginas que podem ser necessárias pela verificação (ou pesquisa).

Dependendo da ordem na qual as E / S realmente concluem e disponibilizam linhas para o processador de consultas (entre outras coisas), o número de páginas realmente tocadas (leituras lógicas) ou fisicamente lidas pode variar. Observe, em particular, que a busca antecipada atrasada da pesquisa também contribui para as leituras lógicas quando verifica se uma página necessária para a pesquisa já está na memória ou não.

Portanto, tudo se resume ao tempo detalhado das operações sobrepostas: O processador de consultas começará a desligar o pipeline de execução de consultas assim que o número necessário de linhas (100) for visto no iterador Principal. Quantas E / Ss assíncronas (leitura antecipada ou pré-busca) foram emitidas ou concluídas nesse ponto são essencialmente não determinísticas.

Você pode desativar a pré-busca de junção de loops aninhados com o sinalizador de rastreamento 8744 para explorar isso ainda mais. Isso removerá a WithOrderedPrefetchpropriedade da associação de loops aninhados. Eu costumo usar OPTION (QUERYTRACEON 8744)na própria consulta. De qualquer forma, você precisa ter certeza de que não está reutilizando um plano em cache que tenha a pré-busca. Limpe o cache do plano toda vez ou force uma recompilação de consulta OPTION (RECOMPILE).

As leituras lógicas são uma medida simples do número de páginas de cache tocadas em nome da consulta. Onde a leitura antecipada (e / ou pré-busca) está ativada, mais (e diferentes!) Páginas de índice e dados podem ser tocadas para emitir essa leitura antecipada ou como parte da atividade de pré-busca.

Paul White 9
fonte