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 / 250474
Accepted
Ian Boyd
Ian Boyd
Asked: 2019-10-08 13:35:11 +0800 CST2019-10-08 13:35:11 +0800 CST 2019-10-08 13:35:11 +0800 CST

O custo do operador não deveria ser pelo menos tão grande quanto o custo de E/S ou CPU que o compreende?

  • 772

Eu tenho uma consulta em um servidor que o otimizador estima que terá um custo de 0,01. Na realidade acaba por correr muito mal.

  • ele acaba executando uma verificação de índice clusterizado

Nota : Você pode encontrar o ddl, sql, tabelas, etc. aqui no Stackoverflow . Mas essa informação, embora interessante, não é importante aqui - o que é uma questão não relacionada. E essa pergunta nem precisa de DDL.

Se eu forçar o uso de uma busca de índice de cobertura, ele estima que o uso desse índice terá um custo de subárvore de 0,04.

  • varredura de índice clusterizado: 0,01
  • cobrindo a varredura do índice: 0,04

Portanto, não é de surpreender que o servidor opte por usar o plano que:

  • na verdade, causa 147.000 leituras lógicas do índice clusterizado
  • em vez das 16 leituras muito mais rápidas de um índice de cobertura

Servidor A:

| Plan                                       | Cost      | I/O Cost    | CPU Cost  |
|--------------------------------------------|-----------|-------------|-----------|
| clustered index scan (optimizer preferred) | 0.0106035 | 116.574     | 5.01949   | Actually run extraordinarily terrible (147k logical reads, 27 seconds)
| covering index seek (force hint)           | 0.048894  |   0.0305324 | 0.0183616 | actually runs very fast (16 logical reads, instant)

Isto é com estatísticas atualizadas COM FULLSCAN nada menos.

Tente em outro servidor

Então eu tento em outro servidor. Recebo estimativas da mesma consulta, com uma cópia recente do banco de dados de produção, também com estatísticas atualizadas (COM FULLSCAN).

  • Este outro servidor também é SQL Server 2014
  • mas ele percebe corretamente que as varreduras de índice clusterizado são ruins
  • e naturalmente prefere a busca do índice de cobertura (porque o custo é 5 ordens de magnitude menor!)

Servidor B :

| Plan                                      | Cost        | I/O Cost   | CPU Cost  |
|-------------------------------------------|-------------|------------|-----------|
| Clustered index scan (force hint)         | 115.661     |   110.889  | 4.77115   | Runs extraordinarily terrible as server A (147k logical reads, 27 seconds)
| Covering index seek (optimizer preferred) |   0.0032831 |   0.003125 | 0.0001581 | Runs fast (16 logical reads, near instant)

O que não consigo descobrir é porque para esses dois servidores, com cópias quase idênticas do banco de dados, ambos com estatísticas atualizadas, ambos SQL Server 2014:

  • pode-se executar a consulta tão corretamente
  • o outro cai morto

Eu sei que parece um caso clássico de estatísticas desatualizadas. Ou planos de execução em cache ou sniffing de parâmetros. Mas essas consultas de teste estão sendo emitidas com OPTION(RECOMPILE), por exemplo:

SELECT MIN(RowNumber) FROM Transactions
WITH (index=[IX_Transactions_TransactionDate]) WHERE TransactionDate >= '20191002 04:00:00.000' OPTION(RECOMPILE)

Se você olhar de perto, parece que a estimativa do "operador" está errada

A varredura de índice clusterizado é uma coisa ruim. E um dos servidores sabe disso. É uma operação muito cara, e a operação de varredura deve me dizer isso.

Se eu forçar a verificação de índice clusterizado e observar as operações de verificação estimadas em ambos os servidores, algo salta à vista:

insira a descrição da imagem aqui

| Cost                | Server A    | Server B   |
|---------------------|-------------|------------|
| I/O Cost            | 116.573     | 110.889    |
| CPU Cost            |   5.01945   |   4.77155  |
| Total Operator Cost |   0.0106035 | 115.661    |
                        mistakenly  | avoids it
                          uses it   |

O custo do operador no servidor A é muito baixo.

  • o custo de E/S é razoável
  • o custo da CPU é razoável
  • mas em conjunto, o custo geral do Operador é 4 ordens de magnitude muito baixo.

Isso explica por que está escolhendo erroneamente o plano de execução ruim; simplesmente tem um custo de operador ruim . O servidor B descobriu isso corretamente e evita a verificação de índice clusterizado.

O operador não é = cpu + io?

Em quase todos os nós do plano de execução sobre os quais você passará o mouse e em todas as capturas de tela dos planos de execução no dba, stackoverflow e em todos os blogs, você verá isso sem falhas:

operatorCost >= max(cpuCost, ioCost)

E, na verdade, geralmente é :

operatorCost = cpuCost + ioCost

Então o que está acontecendo aqui?

O que pode explicar o servidor decidir que os custos de 115 + 5 são quase nada e, em vez disso, decide algo 1/10000 desse custo?

Eu sei que o SQL Server tem opções para ajustar o peso interno aplicado às operações de CPU e E/S:

DBCC    TRACEON (3604);     -- Show DBCC output
DBCC    SETCPUWEIGHT(1E0);  -- Default CPU weight
DBCC    SETIOWEIGHT(0.6E0); -- I/O multiplier = 0.6
DBCC    SHOWWEIGHTS;        -- Show the settings

E quando você fizer isso, o custo do operador pode acabar abaixo do custo de CPU + E/S:

insira a descrição da imagem aqui

Mas ninguém tem brincado com eles. É possível que o SQL Server tenha algum ajuste automático de peso baseado no ambiente, ou baseado em alguma comunicação com o subsistema de disco?

Se o servidor fosse uma máquina virtual, usando um disco SCSI virtual, conectado por um link de fibra a uma Storage Area Network (SAN), ele poderia decidir que os custos de CPU e E/S podem ser ignorados?

Exceto que não pode ser alguma coisa de ambiente permanente neste servidor, porque todas as outras consultas que encontrei se comportam corretamente:

insira a descrição da imagem aqui

 I/O:       0.0112613
 CPU:      +0.0001
           =0.0113613 (theoretical)
 Operator:  0.0113613 (actual)

O que pode explicar o servidor não tomar:

I/O Cost + Cpu Cost = Operator Cost

corretamente nesta instância ?

SQL Server 2014 SP2.

sql-server sql-server-2014
  • 4 4 respostas
  • 634 Views

4 respostas

  • Voted
  1. Josh Darnell
    2019-10-08T19:35:05+08:002019-10-08T19:35:05+08:00

    Metas de linha

    Se uma meta de linha for definida na consulta, isso poderá afetar as estimativas de linha e o custo.

    Você pode confirmar se isso está causando o problema executando a consulta com o sinalizador de rastreamento 4138 ativado (o que removerá a influência do objetivo da linha).

    Tamanho do conjunto de buffers

    O custo estimado para algumas operações de E/S pode ser reduzido se houver um pool de buffers maior disponível (o servidor com custo reduzido tem 14 GB de RAM, versus 6 GB na outra máquina).

    Você pode verificar a influência desse comportamento procurando por "EstimatedPagesCached" no XML do plano. Um valor mais alto para essa propriedade pode reduzir o custo de E/S de partes do plano de execução que potencialmente acessam os mesmos dados.

    Agendadores disponíveis

    Para uma consulta paralela, o custo de CPU de um operador pode ser reduzido em até "# de agendadores / 2". Você pode verificar qual valor isso tem procurando por "EstimatedAvailableDegreeOfParallelism" no XML do plano.

    Menciono isso porque notei que a "consulta lenta" rodava em um servidor com 4 núcleos, enquanto a mais rápida rodava em um servidor com 1 núcleo.

    Os custos são estranhos e quebrados

    Forrest fala sobre várias maneiras diferentes pelas quais os custos podem acabar não fazendo sentido em seu blog: Percentage Non Grata

    • 4
  2. Best Answer
    Shaulinator
    2019-11-08T11:33:28+08:002019-11-08T11:33:28+08:00

    O custo do operador não deveria ser pelo menos tão grande quanto o custo de E/S ou CPU que o compreende?

    Depende.

    É uma pena que outra pessoa tenha deletado seu post porque eu tive ideias semelhantes.

    Metas de linha

    Isso não é o que você está enfrentando com base nas capturas de tela, mas é um fator no cálculo do custo do Operador. Os custos de E/S e CPU não são dimensionados, eles mostrarão um custo por execução se uma meta de linha não estiver em vigor. O custo do operador é dimensionado para mostrar a meta da linha. Esta é uma instância em que I/O e CPU não compreendem exatamente o custo do Operador, o número estimado de execuções é algo a ser levado em consideração. Como você vê essas estatísticas depende se você está olhando para a entrada interna ou externa.

    Fonte : Inside the Optimizer: Row Goals In Depth por Paul White - 18 de agosto de 2010 ( arquivo )

    Uso do buffer pool

    Isso pode ser um fator que está afetando você.

    O custo total de uma operação deve ser o número de execuções multiplicado pelo custo da CPU, mais uma fórmula mais complexa para o número de IO necessário. A fórmula para E/S representa a probabilidade de que um E/S já esteja na memória depois que várias páginas já foram acessadas. Para tabelas grandes, ele também modela as chances de que uma página acessada anteriormente já tenha sido despejada quando for necessária novamente. O custo da subárvore representa o custo da operação atual mais todas as operações que alimentam a operação atual.

    Fonte : Modelo de Custo do Plano de Execução por Joe Chang - julho de 2009 ( arquivo )

    Para o seu problema

    Podemos ver em suas capturas de tela que você tem um custo de subárvore muito interessante no servidor que não está funcionando bem. O interessante é que ele tem mais memória para usar e menos CPU.

    As informações acima me indicam que você provavelmente tem um problema com o custo da subárvore e o custo do operador é um sintoma.

    ...o Custo Estimado da Subárvore, são os custos cumulativos (somados na ordem NodeID) de cada operador individual.

    Fonte : Custos reais do plano de execução por Grant Fritchey - 20 de agosto de 2018 ( arquivo )

    Acho que a resposta está nestas frases:

    A fórmula para E/S representa a probabilidade de que um E/S já esteja na memória depois que várias páginas já foram acessadas. Para tabelas grandes, ele também modela as chances de que uma página acessada anteriormente já tenha sido despejada quando for necessária novamente.

    O que eu acho que está acontecendo com você:

    1. A configuração do hardware é diferente. Ram/CPU/Disco, não é a mesma coisa e está influenciando nas estimativas.
    2. Arquivos de dados físicos. Como você fez uma cópia? Eu recomendaria que a única maneira de realmente replicar isso é fazer um backup/restauração com os arquivos de dados.
    3. Você tentou limpar o cache e forçar uma recompilação? Eu me pergunto no que isso resultaria.

    Caso contrário, eu adoraria ver os planos de consulta estimados e reais para mergulhar mais fundo no que parece estar acontecendo.

    IMPORTANTE, ISSO VAI DOER (Você pode ser demitido) SE VOCÊ EXECUTAR ISSO EM PRODUÇÃO SEM ENTENDER O QUE VAI ACONTECER E SEM PLANEJAR ISSO. É assim que eu limparia o cache para testar novamente com a recompilação.


    Diferentes maneiras de liberar ou limpar o cache do SQL Server por Bhavesh Patel - 31 de março de 2017 ( arquivo )

    • DBCC FREESYSTEMCACHE
    • DBCC FREESESSIONCACHE
    • DBCC FREEPROCCACHE
    • 3
  3. dbilid
    2019-11-09T15:22:31+08:002019-11-09T15:22:31+08:00

    Para mim, parece absolutamente normal que o servidor A escolha a verificação de índice clusterizado. Esta é a melhor decisão dado o conhecimento que o otimizador tem. O estranho é que o servidor B não escolhe o mesmo. Acho que tenho uma resposta para isso, mas primeiro deixe-me explicar por que o otimizador deve escolher a verificação de índice clusterizado.

    A razão básica tem a ver com o fato de achar que os valores em RowNumber e TransactionDate são independentes. Como diz aqui :

    Independence: Data distributions on different columns are independent unless correlation information is available.

    And the query is

    SELECT MIN(RowNumber)   FROM Transactions WHERE TransactionDate >= '20191002 04:00:00.000'
    

    The option are: 1) to start scanning the clustered index, which is sorted on RowNumber, and stop as soon it will encounter the first tuple with TransactionDate >= '20191002 04:00:00.000' which will be the actual answer to the query 2) to search the nonclustered index of TransactionDate for value '20191002 04:00:00.000' and then keep scanning the rest of the index from that value onward, keeping the minimum RowNumber that it will find

    I am assuming here that value '20191002 04:00:00.000' is among the largest values in column TransactionDate. Actually, let's assume that it is larger than 95% of the values. Given the independence assumption, in option 1, it reasonable to assume that the answer will be found in a single disk fetch, as each tuple scanned has 5% probability to be the final answer. In option 2, searching the index for the specific date, already involves more disk page fetches, and then we also have to scan the 5% of the index. In reality though, as values in the two columns as directly correlated, what seems to the optimizer as the best option, ends up scanning 95% of the clustered index.

    Então, por que o Servidor B não escolhe varrer o índice clusterizado? Obviamente, no Servidor B o índice clusterizado NÃO é classificado em RowNumber, como podemos ver nos planos postados na pergunta original: In server A result of scan is sorted, whereas in Server B it is not

    Então, por que CPU_cost + I/O_cost >> custo. Parece que o SQL Server para verificação de índice clusterizado relata o custo total de CPU e E/S da tabela, mesmo que seja apenas uma verificação parcial, e relata apenas a estimativa real com base na rapidez com que encontrará o valor esperado como custo total. Você pode ver exatamente o mesmo comportamento no plano postado aqui

    E quanto ao que pode ser feito, se RowNumber e TransactionDate estão sempre aumentando, a consulta pode ser reescrita da seguinte forma:

    SELECT RowNumber FROM Transactions WHERE TransactionDate >= '20191002 04:00:00.000' ou por TransactionDate LIMIT 1

    • 3
  4. simon coleman
    2019-11-08T10:12:02+08:002019-11-08T10:12:02+08:00

    Podemos presumir que os servidores são genuinamente idênticos?

    • contagem de CPU
    • RAM
    • nível do pacote de serviço sql
    • nível de compatibilidade do banco de dados

    Percebi uma pequena alteração nos custos da etapa de consulta retornados para um plano de execução do SP após alterar o nível de compatibilidade do banco de dados em um servidor sql2012. (db ocioso, obteve o primeiro plano xml, aplicou a mudança de opção, recompilou o sp, obteve o segundo plano xml) O plano em si parece idêntico. Mais opções estão disponíveis no otimizador, possivelmente calculando de forma ligeiramente diferente. Se você tiver um patch / compatibilidade diferente nos servidores 2x, isso poderá resultar no plano real sendo mais radicalmente diferente (errado ..)

    • 2

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