AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / dba / Perguntas / 281057
Accepted
Kirk Saunders
Kirk Saunders
Asked: 2020-12-08 10:21:10 +0800 CST2020-12-08 10:21:10 +0800 CST 2020-12-08 10:21:10 +0800 CST

Cláusula WHERE Compare VarChar(n) Coluna = VarChar(MAX) Variável Resultados em Comparação de Desigualdades e Baixo Desempenho de Consulta

  • 772

Hoje cedo eu estava trabalhando em um Reporting Stored Procedureque teve um desempenho ruim. Consegui corrigir o problema alterando uma estática variableque continha uma string de dez caracteres ou menos de VARCHAR(MAX)para VARCHAR(10). Estou procurando entender por que isso teria feito a diferença.

Detalhes Adicionais Se Necessário

A consulta original é muito maior do que o que precisa ser analisado, mas eu vi as coisas abaixo acontecendo, ao juntar o fundamental tablea um Key-Value Pair table, estávamos retornando uma tonelada a mais rowsdo que era realmente necessário (em alguns casos, mais de 14 bilhões de linhas para uma saída final de ~60.000 linhas) e tivemos algumas operações extras (particularmente o Lazy Table Spool). A imagem dessa parte do Plano de Consulta está abaixo: Recorte do Plano de Execução Original

Eu podia ver que uma parte estranha do plano de execução era como @ProgramID variableestava sendo tratado. Essa variável é usada como [Column] = @ProgramIDe Columnfaz parte das tabelas Non-Clustered Indexe é um arquivo VarChar(10). Mas ainda estamos fazendo um Inequality Searchem vez de um Equality Search.

Plano de Execução Original Buscar Fragmento de Predicado

Depois de modificar isso parameter/variablede VarChar(Max)para VarChar(10). O execution timetempo caiu de várias horas para cerca de 30 segundos e o plano tinha uma estrutura bem diferente. Olhando para um trecho semelhante do plano de execução, não estávamos retornando tantas linhas, não temos as operações extras e estávamos fazendo um equality searchon [Column] = @ProgramID(novamente Columnfaz parte das tabelas Non-Clustered Indexe é um VarChar(10)). Novo trecho do plano de execução

Novo Plano de Execução Buscar Fragmento de Predicado

Abaixo está uma consulta simplificada que mostra um pouco desse comportamento (não temos todas as etapas extras, mas a diferença Seek Predicate ainda está lá): ( Paste The Plan )

DECLARE @CompanyID VarChar(10) = 'RxCRoads'
        ,@ClientID VarCHar(10) = 'Amgen'
        ,@ProgramID VarChar(MAX) = 'Foundation'
        ,@StartDate DATETIME = '2020-01-01'
        ,@EndDate DATETIME = '2020-12-07'
        ,@RxOnly INT = 9

SELECT PC.CompanyID,
PC.ClientID,
PC.ProgramID,
PC.PatientID,
PC.CaseID,
RxOnly.[Value] AS RxOnly
FROM PATIENTCASES PC
    LEFT OUTER JOIN PatientCaseDetail RxOnly
        ON RxOnly.CompanyId = PC.CompanyID
        AND RxOnly.ClientId = PC.ClientID
        AND RxOnly.ProgramId = PC.ProgramID
        AND RxOnly.PatientID = PC.PatientID
        AND RxOnly.CaseID = PC.CaseID
        AND RxOnly.PatientCaseAdditionalElementId = @RxOnly
WHERE PC.CompanyID = @CompanyID
AND PC.ClientID = @ClientID
AND PC.ProgramID = @ProgramID
AND PC.CaseCreateDateTime >= @StartDate
AND PC.CaseCreateDateTime < @EndDate

Apenas alterar o @ProgramID VarChar(MAX) = 'Foundation')para @ProgramID VarChar(10) = 'Foundation'retorna um plano mais ágil e melhor desempenho (mesmo que não seja realmente perceptível nesta consulta específica). ( Colar o plano )

Existe algum motivo específico pelo qual essa mudança no tamanho do tipo de dados resultaria na mudança no plano de execução? Executar a mesma consulta com @ProgarmId VarChar(8000)em vez de @Program VarChar(10)não tem diferença perceptível de @Program VarChar(10). ( Colar o plano )

Meu palpite é que VarChar(MAX)tem regras de comparação diferentes devido ao seu tamanho, e isso é apenas um estado do que VarChar(MAX)é. Mas eu não sabia se alguém tinha uma resposta melhor/mais técnica do que eu para que eu possa aplicar melhor essa lição no futuro.

sql-server query-performance
  • 2 2 respostas
  • 529 Views

2 respostas

  • Voted
  1. Best Answer
    Erik Darling
    2020-12-08T15:09:34+08:002020-12-08T15:09:34+08:00

    Os problemas

    Você tem duas coisas trabalhando contra você:

    • Variáveis ​​locais geralmente têm efeitos colaterais estranhos
    • Os tipos de dados MAX não podem ser enviados, então você acaba com filtros atrasados ​​em seus planos de consulta

    Algumas leituras adicionais:

    • Mais um post sobre variáveis ​​locais
    • Tipos de dados MAX fazem o quê?
    • Por que você não deve ignorar os operadores de filtro nos planos de consulta Parte 1 | Parte 2
    • Por que o SQL Server usa um plano de execução melhor quando inline a variável?

    Em particular

    No seu pior plano, existem dois operadores de filtro:

    NOZES

    Cada um está lá para lidar com o tipo MAX no @ProgramId. O comprimento do parâmetro não importa muito até você atingir o tipo máximo, desde que seja o tipo correto, por exemplo varchar = varcharounvarchar = nvarchar

    Você também pode ver GetRangeThroughMismatchedTypeou GetRangeThroughConvertlá para lidar com uma date\ datetimeincompatibilidade:

    • Cast to date é sargável, mas é uma boa ideia?

    Você pode encontrar algum alívio geral adicionando uma dica de recompilação, mas isso não resolverá o problema que você está tendo em torno da variável MAX.

    • 4
  2. Yunus UYANIK
    2020-12-08T11:46:37+08:002020-12-08T11:46:37+08:00

    O comprimento é uma das coisas usadas pelo otimizador para determinar o plano de execução ideal.

    Ao usar MAX, se o SQL Server quiser usar um índice, ele deve converter igual sua variável para a coluna.

    Podemos ver Compute Scalaro operador em seu plano de execução. É um operador leve, mas usando Compute Scalarcom Nested Loopserá pior desempenho. Porque Nested Loopvai para a Compute Scalaroperação para cada linha que vem.

    <ComputeScalar>
      <DefinedValues>
        <DefinedValue>
          <ValueVector>
            <ColumnReference Column="Expr1003"/>
            <ColumnReference Column="Expr1004"/>
            <ColumnReference Column="Expr1002"/>
          </ValueVector>
          <ScalarOperator ScalarString="GetRangeWithMismatchedTypes([@ProgramID],[@ProgramID],(62))">
            <Intrinsic FunctionName="GetRangeWithMismatchedTypes">
              <ScalarOperator>
                <Identifier>
                  <ColumnReference Column="@ProgramID"/>
                </Identifier>
              </ScalarOperator>
              <ScalarOperator>
                <Identifier>
                  <ColumnReference Column="@ProgramID"/>
                </Identifier>
              </ScalarOperator>
              <ScalarOperator>
                <Const ConstValue="(62)"/>
              </ScalarOperator>
            </Intrinsic>
          </ScalarOperator>
        </DefinedValue>
      </DefinedValues>
      <RelOp AvgRowSize="0" EstimateCPU="0" EstimateIO="0" EstimateRebinds="0" EstimateRewinds="0" EstimatedExecutionMode="Row" EstimateRows="1" LogicalOp="Constant Scan" NodeId="4" Parallel="false" PhysicalOp="Constant Scan" EstimatedTotalSubtreeCost="0">
        <OutputList/>
        <RunTimeInformation>
          <RunTimeCountersPerThread Thread="0" ActualRows="1" Batches="0" ActualEndOfScans="1" ActualExecutions="1" ActualExecutionMode="Row" ActualElapsedms="0" ActualCPUms="0"/>
        </RunTimeInformation>
        <ConstantScan/>
      </RelOp>
    </ComputeScalar>
    

    VARCHAR(N)e VARCHAR(MAX) meio que dois tipos de dados diferentes, como DateTimee Date. VARCHAR(MAX)é BLOBe VARCHAR(n) In-Row data. Portanto, se o tipo de coluna não for VARCHAR(MAX), o SQL Server precisará converter sua variável para usar o índice.

    Há uma postagem de blog de mergulho profundo de Paul White. Mas, não inclui o seu exemplo.

    • 0

relate perguntas

  • SQL Server - Como as páginas de dados são armazenadas ao usar um índice clusterizado

  • Preciso de índices separados para cada tipo de consulta ou um índice de várias colunas funcionará?

  • Quando devo usar uma restrição exclusiva em vez de um índice exclusivo?

  • Quais são as principais causas de deadlocks e podem ser evitadas?

  • Como determinar se um Índice é necessário ou necessário

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve