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 / 57296
Accepted
Chris L
Chris L
Asked: 2014-01-23 07:05:19 +0800 CST2014-01-23 07:05:19 +0800 CST 2014-01-23 07:05:19 +0800 CST

Por que a subconsulta usa paralelismo e a junção não?

  • 772

Por que o servidor SQL usa paralelismo ao executar esta consulta que usa uma subconsulta, mas não ao usar uma junção? A versão de junção é executada em série e leva cerca de 30 vezes mais para ser concluída.

Versão de entrada: ~30 segundos

insira a descrição da imagem aqui

Versão da subconsulta: <1 segundo

insira a descrição da imagem aqui

EDIT: Versões XML do plano de consulta:

Versão JOIN

versão SUBQUERY

sql-server join
  • 1 1 respostas
  • 1382 Views

1 respostas

  • Voted
  1. Best Answer
    Martin Smith
    2014-01-23T16:00:17+08:002014-01-23T16:00:17+08:00

    Conforme já indicado nos comentários, parece que você precisa atualizar suas estatísticas.

    O número estimado de linhas que saem da junção entre locatione testrunsé muito diferente entre os dois planos.

    Estimativas do plano de junção: 1

    Plano 1

    Estimativas do plano de subconsulta: 8.748

    insira a descrição da imagem aqui

    O número real de linhas que saem da junção é 14.276.

    É claro que não faz sentido intuitivo que a versão de junção deva estimar que 3 linhas devem vir locatione produzir uma única linha unida, enquanto a subconsulta estima que uma única dessas linhas produzirá 8.748 da mesma junção, mas mesmo assim consegui para reproduzir isso.

    Isso parece acontecer se não houver cruzamento entre os histogramas quando as estatísticas são criadas. A versão de junção assume uma única linha. E a busca de igualdade única da subconsulta assume as mesmas linhas estimadas que uma busca de igualdade em relação a uma variável desconhecida.

    A cardinalidade das execuções de teste é 26244. Supondo que seja preenchido com três IDs de local distintos, a consulta a seguir estima que 8,748as linhas serão retornadas ( 26244/3)

    declare @i int
    
    SELECT *
    FROM   testruns AS tr
    WHERE  tr.location_id = @i
    

    Dado que a tabela locationscontém apenas 3 linhas, é fácil (se assumirmos que não há chaves estrangeiras) criar uma situação em que as estatísticas são criadas e, em seguida, os dados são alterados de uma forma que afeta drasticamente o número real de linhas retornadas, mas é insuficiente para disparar a atualização automática de estatísticas e recompilar o limite.

    Como o SQL Server obtém o número de linhas que saem dessa junção tão errado, todas as outras estimativas de linha no plano de junção são enormemente subestimadas. Além de significar que você obtém um plano serial, a consulta também recebe uma concessão de memória insuficiente e as classificações e junções de hash se espalham para tempdb.

    Um cenário possível que reproduz as linhas reais versus estimadas mostradas em seu plano está abaixo.

    CREATE TABLE location
      (
         id       INT CONSTRAINT locationpk PRIMARY KEY,
         location VARCHAR(MAX) /*From the separate filter think you are using max?*/
      )
    
    /*Temporary ids these will be updated later*/
    INSERT INTO location
    VALUES      (101, 'Coventry'),
                (102, 'Nottingham'),
                (103, 'Derby')
    
    CREATE TABLE testruns
      (
         location_id INT
      )
    
    CREATE CLUSTERED INDEX IX ON testruns(location_id)
    
    /*Add in 26244 rows of data split over three ids*/
    INSERT INTO testruns
    SELECT TOP (5984) 1
    FROM   master..spt_values v1, master..spt_values v2
    UNION ALL
    SELECT TOP (5984) 2
    FROM   master..spt_values v1, master..spt_values v2
    UNION ALL
    SELECT TOP (14276) 3
    FROM   master..spt_values v1, master..spt_values v2
    
    /*Create statistics. The location_id histograms don't intersect at all*/
    UPDATE STATISTICS location(locationpk) WITH FULLSCAN;    
    UPDATE STATISTICS testruns(IX) WITH FULLSCAN;
    
    /* UPDATE location.id. Three row update is below recompile threshold*/
    UPDATE location
    SET    id = id - 100
    

    Em seguida, executar as seguintes consultas fornece a mesma discrepância estimada versus real

    SELECT *
    FROM   testruns AS tr
    WHERE  tr.location_id = (SELECT id
                             FROM   location
                             WHERE  location = 'Derby')
    
    SELECT *
    FROM   testruns AS tr
           JOIN location loc
             ON tr.location_id = loc.id
    WHERE  loc.location = ( 'Derby' ) 
    
    • 12

relate perguntas

  • Qual é a diferença entre um INNER JOIN e um OUTER JOIN?

  • 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 é a saída de uma instrução JOIN?

  • 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