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 / 72726
Accepted
Vojtěch Dohnal
Vojtěch Dohnal
Asked: 2014-07-31 02:37:32 +0800 CST2014-07-31 02:37:32 +0800 CST 2014-07-31 02:37:32 +0800 CST

Busca de índice muito mais lenta com condição OR em comparação com SELECTs separados

  • 772

Com base nessas perguntas e nas respostas dadas:

SQL 2008 Server - perda de desempenho possivelmente relacionada a uma tabela muito grande

Tabela grande com dados históricos aloca muito do SQL Server 2008 Std. memória - perda de desempenho para outros bancos de dados

Eu tenho uma tabela em um banco de dados SupervisionP definida assim:

CREATE TABLE [dbo].[PenData](
    [IDUkazatel] [smallint] NOT NULL,
    [Cas] [datetime2](0) NOT NULL,
    [Hodnota] [real] NULL,
    [HodnotaMax] [real] NULL,
    [HodnotaMin] [real] NULL,
 CONSTRAINT [PK_Data] PRIMARY KEY CLUSTERED 
(
    [IDUkazatel] ASC,
    [Cas] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

ALTER TABLE [dbo].[PenData]  WITH NOCHECK ADD  CONSTRAINT [FK_Data_Ukazatel] FOREIGN KEY([IDUkazatel])
REFERENCES [dbo].[Ukazatel] ([IDUkazatel])

ALTER TABLE [dbo].[PenData] CHECK CONSTRAINT [FK_Data_Ukazatel]

Ele contém cerca de 211 milhões de linhas.

Eu corro a seguinte declaração:

DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;

SET @t1 = GETDATE();
SELECT min(cas) from PenData p WHERE IDUkazatel=24
SELECT min(cas) from PenData p WHERE IDUkazatel=25
SET @t2 = GETDATE();
SELECT DATEDIFF(millisecond,@t1,@t2) AS elapsed_ms;


SET @t1 = GETDATE();
SELECT min(cas) from PenData p WHERE IDUkazatel=24 OR IDUkazatel=25 
SET @t2 = GETDATE();
SELECT DATEDIFF(millisecond,@t1,@t2) AS elapsed_ms;

O resultado é mostrado aqui:

Plano de execução

O terceiro SELECT também carrega muito mais dados no cache de memória do SQL Server.

Por que o terceiro SELECT é muito mais lento (8,5 s) do que os dois primeiros SELECTs (16 ms)? Como posso melhorar o desempenho do terceiro select com OR? Eu quero executar o seguinte comando SQL, mas parece-me que criar cursor e executar consultas separadas é muito mais rápido do que uma única seleção neste caso.

 SELECT MIN(cas) from PenData p WHERE IDUkazatel IN (SELECT IDUkazatel FROM  ...)

EDITAR

Como David sugeriu, passei o mouse sobre a seta gorda:

FatArrow

sql-server sql-server-2008
  • 1 1 respostas
  • 6734 Views

1 respostas

  • Voted
  1. Best Answer
    David Spillett
    2014-07-31T03:19:56+08:002014-07-31T03:19:56+08:00

    Para as duas primeiras consultas, tudo o que ele precisa fazer é verificar no índice clusterizado a primeira entrada para esse valor de IDUkazatel- devido à ordem do índice, essa linha será o valor mais baixo para cas para esse valor de IDUkazatel.

    Na segunda consulta, essa otimização não é valor e provavelmente está procurando a primeira linha para , em IDUkazatel=24seguida, digitalizar o índice até a última linha IDUkazatel=25para encontrar o valor mínimo de castodas essas linhas.

    Se você passar o mouse sobre a seta gorda, verá que ela está lendo muitas linhas (certamente todas as de 24, provavelmente todas as de 25 também), enquanto as setas finas na saída do plano para as outras duas mostram a topação que faz com que apenas considere uma linha.

    Você pode tentar executar cada consulta e obter o mínimo para os mínimos encontrados:

    SELECT MIN(cas)
    FROM   (
            SELECT cas=MIN(cas) FROM PenData p WHERE p.IDUkazatel = 24
            UNION ALL
            SELECT cas=MIN(cas) FROM PenData p WHERE p.IDUkazatel = 25
        ) AS minimums
    

    Dito isso, parece que você tem uma tabela com valores em vez de uma cláusula IDUkazatelexplícita . ORO código abaixo funcionará com essa disposição, basta substituir o nome da tabela @Tpelo nome da tabela que contém os IDUkazatelvalores:

    SELECT 
        MinCas = MIN(CA.PartialMinimum)
    FROM @T AS T
    CROSS APPLY 
    (
        SELECT 
            PartialMinimum = MIN(PD.Cas)
        FROM dbo.PenData AS PD
        WHERE 
            PD.IDUkazatel = T.IDUkazatel
    ) AS CA;
    

    Em um mundo ideal, o otimizador de consulta do SQL Server executaria essa reescrita para você, mas nem sempre considera essa opção hoje.

    • 11

relate perguntas

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

  • Quanto "Padding" coloco em meus índices?

  • Existe um processo do tipo "práticas recomendadas" para os desenvolvedores seguirem para alterações no banco de dados?

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

  • Downgrade do SQL Server 2008 para 2005

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