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 / 188704
Accepted
user45867
user45867
Asked: 2017-10-18 14:00:37 +0800 CST2017-10-18 14:00:37 +0800 CST 2017-10-18 14:00:37 +0800 CST

Por que "select *" é mais rápido que "select top 500 *" no SQL Server? [duplicado]

  • 772
Essa pergunta já tem respostas aqui :
Pergunta de desempenho 'SELECT TOP' (2 respostas)
Como (e por que) o TOP impacta um plano de execução? (2 respostas)
Fechado há 5 anos .

Eu tenho uma visão, complicated_view-- existem algumas junções e cláusulas where. Agora,

select * from complicated_view (9000 records)

é mais rápido, muito mais rápido , do que

select top 500 * from complicated_view

Estamos falando de 19 segundos contra mais de 5 minutos.

A primeira consulta retorna todos os 9.000 registros. Como só pegar o top 500 é ridiculamente mais longo?

Obviamente, vou examinar os planos de execução aqui ---- mas assim que descobrir por que o SQL Server está executando o "top 500" de maneira abaixo do ideal, como posso dizer a ele para executar o plano de maneira rápida, como tomar a mesa cheia?

Claro, eu posso ter que reescrever a visão inteiramente --- mas muito estranho.

Basicamente, estou conectando esta tabela de dados a um software de terceiros que pré-verifica tabelas com uma select top 500 *consulta padrão que não pode ser modificada. Então, além de despejar essa visão em uma tabela real (bastante desleixada) - também não consigo contornar o adendo "top 500".

Este é o SQL Server 2012.

EDIT: Discordo do sinalizador duplicado. A outra pergunta, o top foi mais rápido que todos. Este seria o comportamento ESPERADO, retornando menos linhas. Meu caso é o contrário. Além disso, meu entendimento é que o Top 100 é um algoritmo diferente do Top 100+. Eu nem acho que a pergunta duplicada tem a resposta correta. Ou seja, a consulta TOP X ordenará tabelas potencialmente massivas muito cedo, não DEPOIS de serem agregadas/filtradas/etc. O porquê é um mistério, mas o como está claramente lá.

sql-server performance
  • 1 1 respostas
  • 25154 Views

1 respostas

  • Voted
  1. Best Answer
    Joe Obbish
    2017-10-18T16:01:20+08:002017-10-18T16:01:20+08:00

    Adicionar uma TOPcláusula a uma consulta introduz um objetivo de linha à consulta. O otimizador de consulta tentará usar o fato de não precisar retornar todas as linhas para criar um plano de consulta mais eficiente. A meta de linha pode fazer com que o custo de alguns operadores seja reduzido. A otimização de meta de linha pode funcionar contra o sintonizador de consulta devido a limitações de modelo ou informações incompletas em objetos de estatísticas. Abaixo, tenho uma demonstração em relação a uma visualização simples para a qual a adição TOP 500degrada o desempenho.

    Primeiro insira apenas números inteiros ímpares em uma tabela. Observe que estou reunindo estatísticas completas no final.

    DROP TABLE IF EXISTS dbo.ODD;
    
    CREATE TABLE dbo.ODD (
        ID BIGINT NOT NULL,
        FLUFF VARCHAR(10)
    );
    
    INSERT INTO dbo.ODD WITH (TABLOCK)
    SELECT TOP (100000)
      -1 + 2 * ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
    , REPLICATE('FLUFF', 2)
    FROM master..spt_values t1
    CROSS JOIN master..spt_values t2;
    
    CREATE STATISTICS S ON dbo.ODD (ID) WITH FULLSCAN;
    

    Em seguida, insira apenas números inteiros pares em uma tabela diferente. Estou fazendo algumas coisas com valores repetidos e tamanho de linha para fazer a demonstração funcionar. Eu ainda atualizo as estatísticas na íntegra no final.

    DROP TABLE IF EXISTS dbo.EVEN;
    
    CREATE TABLE dbo.EVEN (
        ID BIGINT NOT NULL,
        FLUFF VARCHAR(3500)
    );
    
    INSERT INTO dbo.EVEN WITH (TABLOCK)
    SELECT TOP (100000) 
      1000 * FLOOR ( ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) / 500)
    , REPLICATE('FLUFF', 700)
    FROM master..spt_values t1
    CROSS JOIN master..spt_values t2
    
    CREATE STATISTICS S ON dbo.EVEN (ID) WITH FULLSCAN;
    

    Aqui está a definição de visualização:

    CREATE OR ALTER VIEW dbo.TRICKY_VIEW AS
    SELECT o.ID
    FROM dbo.ODD o
    WHERE NOT EXISTS (
        SELECT 1
        FROM dbo.EVEN e WHERE o.ID = e.ID
    );
    

    Considere a seguinte consulta:

    SELECT TOP 500 *
    FROM dbo.TRICKY_VIEW
    OPTION (MAXDOP 1);
    

    Veja como é o plano de consulta:

    plano ruim

    Uma limitação de custo faz com que a varredura completa da EVENtabela no lado interno da junção de loop aninhado tenha um custo relativo baixo. Com base em como construí os dados, sabemos que o otimizador precisará verificar 500 * 100.000 = 50 milhões de linhas da EVENtabela para retornar as primeiras 500 linhas ao cliente. Isso é realmente o que acontece, e a consulta leva cerca de 16 segundos para ser executada na minha máquina:

    plano real ruim

    A remoção da TOPcláusula da consulta fornece um plano diferente e mais eficiente :

    bom plano

    Esta consulta é executada em menos de meio segundo na minha máquina. Apenas 100.000 linhas são lidas da EVENtabela.

    Para o SQL Server 2016 e versões posteriores, você pode contornar esse problema sem alterar a definição da exibição adicionando OPTION (USE HINT('DISABLE_OPTIMIZER_ROWGOAL'))à consulta. Essa dica desativa a otimização da meta de linha no nível da consulta. Para o SQL Server 2012, você pode usar o sinalizador de rastreamento 4138 no nível de consulta via OPTION (QUERYTRACEON 4138), mas isso requer SA.

    Não posso dizer nada sobre sua consulta em particular sem ver os planos de consulta, mas espero que este exemplo ilustre o ponto geral.

    • 29

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

    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