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 / 20178
Accepted
SqlRyan
SqlRyan
Asked: 2012-06-30 12:08:33 +0800 CST2012-06-30 12:08:33 +0800 CST 2012-06-30 12:08:33 +0800 CST

Consulta T-SQL usando um plano completamente diferente, dependendo do número de linhas que estou atualizando

  • 772

Eu tenho uma instrução SQL UPDATE com uma cláusula "TOP (X)" e a linha em que estou atualizando valores tem cerca de 4 bilhões de linhas. Quando uso "TOP (10)", obtenho um plano de execução que é executado quase instantaneamente, mas quando uso "TOP (50)" ou maior, a consulta nunca (pelo menos, não enquanto estou esperando) termina e ele usa um plano de execução completamente diferente. A consulta menor usa um plano muito simples com um par de buscas de índice e uma junção de loop aninhada, onde exatamente a mesma consulta (com um número diferente de linhas na cláusula TOP da instrução UPDATE) usa um plano que envolve duas buscas de índice diferentes , um carretel de mesa, paralelismo e várias outras complexidades.

Usei "OPTION (USE PLAN...)" para forçá-lo a usar o plano de execução gerado pela consulta menor - quando faço isso, posso atualizar até 100.000 linhas em alguns segundos. Eu sei que o plano de consulta é bom, mas o SQL Server só escolherá esse plano por conta própria quando apenas um pequeno número de linhas estiver envolvido - qualquer contagem de linha decentemente grande em minha atualização resultará no plano abaixo do ideal.

Achei que o paralelismo poderia ser o culpado, então comecei MAXDOP 1a consulta, mas sem efeito - essa etapa foi concluída, mas a má escolha/desempenho não. Também corri sp_updatestatsesta manhã para garantir que não era essa a causa.

Anexei os dois planos de execução - o mais curto também é o mais rápido. Além disso, aqui está a consulta em questão (vale a pena notar que o SELECT que incluí parece ser rápido nos casos de contagens de linhas pequenas e grandes):

    update top (10000) FactSubscriberUsage3
               set AccountID = sma.CustomerID
    --select top 50 f.AccountID, sma.CustomerID
      from FactSubscriberUsage3 f
      join dimTime t
        on f.TimeID = t.TimeID
      join #mac sma
        on f.macid = sma.macid
       and t.TimeValue between sma.StartDate and sma.enddate 
     where f.AccountID = 0 --There's a filtered index on the table for this

Aqui está o plano rápido : Plano de Execução Rápida

E aqui está o mais lento : Plano de Execução Lenta

Existe algo óbvio na maneira como estou configurando minha consulta ou no plano de execução fornecido que se prestaria à má escolha que o mecanismo de consulta está fazendo? Se necessário, também posso incluir as definições das tabelas envolvidas e os índices nelas definidos.

Para aqueles que pediram uma versão apenas de estatísticas dos objetos do banco de dados: eu nem sabia que você poderia fazer isso, mas faz todo o sentido! Tentei gerar os scripts para um banco de dados somente de estatísticas para que outros pudessem testar os planos de execução por si mesmos, mas posso gerar estatísticas/histogramas no meu índice filtrado (erro de sintaxe no script, ao que parece), então estou sem sorte lá. Eu tentei remover o filtro e os planos de consulta estavam próximos, mas não exatamente os mesmos, e não quero enviar ninguém em uma perseguição.

Atualização e alguns planos de execução mais completos: Em primeiro lugar, o Plan Explorer do SQL Sentry é uma ferramenta incrível. Eu nem sabia que existia até ver as outras perguntas do plano de consulta neste site, e tinha muito a dizer sobre como minhas consultas estavam sendo executadas. Embora eu não tenha certeza de como resolver o problema, eles deixaram claro qual é o problema.

Aqui está o resumo para 10, 100 e 1.000 linhas - você pode ver que a consulta de 1.000 linhas está muito, muito fora de linha com as outras: Resumo da declaração

Você pode ver que a terceira consulta tem um número ridículo de leituras, então obviamente está fazendo algo completamente diferente. Aqui está o plano de execução estimado, com contagens de linhas. Plano de execução estimado de 1.000 linhas: Plano de execução estimado de 1.000 linhas

E aqui estão os resultados reais do plano de execução (aliás, por "nunca termina", eu quis dizer "acaba em uma hora"). Plano de execução real de 1.000 linhas Plano de execução real de 1.000 linhas

A primeira coisa que notei foi que, em vez de extrair 60 mil linhas da tabela dimTime como esperado, na verdade está extraindo 1,6 bilhão, com um B . Olhando para minha consulta, não tenho certeza de como ela está retirando tantas linhas da tabela dimTime. O operador BETWEEN que estou usando apenas garante que estou extraindo o registro correto do #mac com base no registro de tempo na tabela Fact. No entanto, quando adiciono uma linha à cláusula WHERE onde filtro t.TimeValue (ou t.TimeID) para um único valor, posso atualizar com êxito 100.000 linhas em questão de segundos. Como resultado disso, e como ficou claro nos planos de execução que incluí, é óbvio que o problema é meu cronograma, mas não tenho certeza de como alteraria os critérios de junção para contornar esse problema e manter a precisão . Alguma ideia?

Para referência, aqui está o plano (com contagens de linhas) para a atualização de 100 linhas. Você pode ver que ele atinge o mesmo índice e ainda com uma tonelada de linhas, mas nem de longe a mesma magnitude de um problema. Execução de 100 linhas com contagens de linha : insira a descrição da imagem aqui

sql-server performance
  • 2 2 respostas
  • 2512 Views

2 respostas

  • Voted
  1. Best Answer
    william_a_dba
    2012-06-30T14:55:35+08:002012-06-30T14:55:35+08:00

    O índice em dimTime está mudando. O plano mais rápido é usar um índice _dta. Primeiro, certifique-se de que não está marcado como um índice hipotético em sys.indexes.

    Pensando que você poderia estar ignorando alguma parametrização usando a tabela #mac para filtrar em vez de apenas fornecer as datas de início/término como este WHERE t.TimeValue entre @StartDate e @enddate. Livre-se dessa mesa temporária.

    • 3
  2. usr
    2012-07-01T02:33:10+08:002012-07-01T02:33:10+08:00

    Sem mais informações sobre a contagem de linhas no plano, minha recomendação preliminar é organizar a ordem de junção correta na consulta e forçá-la usando OPTION (FORCE ORDER). Aplique a ordem de junção do primeiro plano.

    • 1

relate perguntas

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

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

  • Onde posso encontrar o log lento do mysql?

  • Como posso otimizar um mysqldump de um banco de dados grande?

Sidebar

Stats

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

    Como ver a lista de bancos de dados no Oracle?

    • 8 respostas
  • Marko Smith

    Quão grande deve ser o mysql innodb_buffer_pool_size?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    restaurar a tabela do arquivo .frm e .ibd?

    • 10 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

    Como selecionar a primeira linha de cada grupo?

    • 6 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
    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
    pedrosanta Listar os privilégios do banco de dados usando o psql 2011-08-04 11:01:21 +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
  • Martin Hope
    bernd_k Quando devo usar uma restrição exclusiva em vez de um índice exclusivo? 2011-01-05 02:32:27 +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