Database
 sql >> Base de Dados >  >> RDS >> Database

Definindo e identificando metas de linha em planos de execução

Introdução


A documentação do produto SQL Server é um pouco leve no tópico de objetivos de linha . As principais referências oficiais estão em:
  • Dicas (Transact-SQL) – Consulta (FAST e DISABLE_OPTIMIZER_ROWGOAL dicas)
  • DBCC TRACEON – sinalizadores de rastreamento (Transact-SQL) (sinalizador de rastreamento 4138)
  • Uma consulta pode levar muito tempo para ser executada se o otimizador de consulta usar o operador Top (KB 2667211)

Quando as pessoas pedem mais informações do que as contidas ali, normalmente eu as encaminhei para um ou mais dos seguintes:
  • Metas de linha em ação pela equipe de otimização de consulta do SQL Server
  • Objetivos de linha revisitados – orientação de dicas FAST também pela equipe de otimização de consulta do SQL Server
  • Gols de linha foram desonestos por Bart Duncan
  • Dentro do Optimizer:linhas detalhadas de metas por mim
  • A dica de ajuste do SSIS que todo mundo sente falta de Rob Farley

Para resumir brevemente:O recurso de meta de linha permite que o otimizador gere um plano de execução (ou parte(s) de um plano de execução) com o objetivo de retornar um certo número de linhas rapidamente. Isso contrasta com o comportamento normal (sem uma meta de linha), que visa encontrar um plano otimizado para o conjunto de resultados potencial completo.

Uma estratégia de meta de linha geralmente significa favorecer operações de navegação sem bloqueio (por exemplo, junções de loops aninhados, buscas de índice e pesquisas) sobre operações de bloqueio baseadas em conjunto, como classificação e hash. Isso pode ser útil sempre que o cliente puder se beneficiar de uma inicialização rápida e fluxo constante de linhas (talvez com um tempo de execução geral mais longo – veja a postagem de Rob Farley acima). Existem também os usos mais óbvios e tradicionais, por exemplo. na apresentação de resultados uma página de cada vez.

Naturalmente, há um elemento de risco envolvido com um plano de metas de linha. Se tudo ocorrer amplamente como o otimizador espera (dadas as informações disponíveis e as suposições de modelagem feitas), o plano de execução começará a transmitir o número de linhas solicitado de forma mais rápida e eficiente do que teria sido o caso sem a meta de linha.

Infelizmente, quando a estratégia de gol de linha dá errado, pode ser um desastre de desempenho (veja o post de Bart Duncan). Isso pode acontecer, por exemplo, quando o otimizador tem informações incompletas, encontra uma distribuição de dados desfavorável ou faz uma suposição insegura. De qualquer forma, a causa do baixo desempenho é quase sempre que muito mais linhas precisam ser processadas em tempo de execução do que o otimizador esperava.

Pode ser muito útil identificar as áreas do plano de execução afetadas por uma meta de linha, pois nos ajuda a entender por que o otimizador fez as escolhas que fez. Isso é particularmente importante quando a lógica de meta de linha produz um resultado adverso. Sem entender o papel desempenhado pela meta de linha, pode parecer que o otimizador simplesmente subestimou o número de linhas, levando as pessoas a procurar nos lugares errados (por exemplo, estatísticas) por uma causa raiz.

Definindo metas de linha


É muito mais fácil procurar efeitos de meta de linha se soubermos quais tipos de coisas podem fazer com que uma meta de linha seja definida em primeiro lugar. A documentação oficial geralmente fala sobre metas de linha sendo associadas às palavras-chave TOP , FAST , IN , e EXISTS . Isso pode deixar o leitor com uma compreensão incompleta ou enganosa, por isso vale a pena dedicar um momento para esclarecer alguns aspectos.

Quero enfatizar logo de início que usar palavras-chave T-SQL específicas em uma consulta não garante que uma meta de linha seja definida . A documentação oficial menciona certas palavras-chave para ajudar as pessoas a identificar cenários comuns em que as metas de linha podem ser introduzido, sem entrar em muitos detalhes técnicos.

Um segundo ponto geral a ter em mente é que uma meta de linha só é definida quando a meta for menor que a estimativa normal . Afinal, não há muito sentido em gerar um fragmento de plano otimizado para 100 linhas se a coisa toda deve produzir apenas 50 linhas de qualquer maneira. Para ser ainda mais claro, este ponto sempre se aplica a todas as maneiras pelas quais uma meta de linha pode ser definida. Se você está esperando uma meta de linha, mas não vê uma, essa é uma causa provável.

Finalmente, para o preâmbulo, observe que as metas de linha são uma coisa de otimização baseada em custo; uma meta de linha afeta as escolhas do otimizador, portanto, se não houver escolhas a serem feitas (ou seja, um plano trivial), não haverá efeito de meta de linha.

Vejamos agora as coisas que podem definir uma meta de linha:

RÁPIDO e TOP


Usando o FAST a dica de consulta é uma maneira confiável de definir uma meta de linha na raiz do plano de execução (sujeito às exceções gerais mencionadas acima). A SET ROWCOUNT n também define uma meta de linha de nível superior semelhante (quando n não é zero, é claro) para as declarações às quais se aplica.

Escrevendo um TOP cláusula em uma consulta também muitas vezes resulta em uma meta de linha. Desde que o plano de execução finalizado apresente um operador Top físico, é provável que pelo menos uma parte do plano abaixo do operador Top tenha sido afetada por uma meta de linha (novamente, os termos e condições gerais se aplicam).

Observe que os principais operadores introduzidos pelo otimizador de consulta (sem um TOP especificado pela consulta cláusula) também pode definir uma meta de linha. Isso é importante, porque há várias maneiras de isso acontecer, por exemplo, ao filtrar um número de linha simples, conforme mostrado na seguinte consulta do AdventureWorks:
SELECT
    THN.RowNum,
    THN.TransactionID 
FROM 
(
    SELECT 
        TH.TransactionID, 
        RowNum = 
            ROW_NUMBER() OVER (
                ORDER BY TH.TransactionID ASC)
    FROM Production.TransactionHistory AS TH
    WHERE
        TH.ProductID = 400
) AS THN
WHERE
    THN.RowNum >= 10
    AND THN.RowNum < 20
ORDER BY
    THN.RowNum ASC;

O plano de execução para essa consulta inclui um operador Top adicionado pelo otimizador (para limitar o número de linhas processadas a 20):