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 / 176724
Accepted
Pரதீப்
Pரதீப்
Asked: 2017-06-20 22:53:31 +0800 CST2017-06-20 22:53:31 +0800 CST 2017-06-20 22:53:31 +0800 CST

Melhoria de desempenho Aplicação externa

  • 772

Eu tenho uma consulta que é um pouco mais lenta.

SELECT b.BreakdownClassificationId,
       k.IsinCode,
       k.SedolCode,
       ClassificationDate,
       NAME,
       InstrumentType,
       GeographicalLocation,
       CapSize,
       Currency,
       ExchangeName,
       HoldingDomicile,
       MaturityDate,
       Sector,
       MajorSector
FROM   #BreakdownSet b
       OUTER apply (SELECT TOP 1 IsinCode,
                                 SedolCode,
                                 ClassificationDate,
                                 NAME,
                                 InstrumentType,
                                 GeographicalLocation,
                                 CapSize CapSize,
                                 Currency,
                                 ExchangeName,
                                 HoldingDomicile,
                                 MaturityDate,
                                 Sector,
                                 MajorSector
                    FROM   dbfinex.dbo.PfPortfolioHoldingClassificationFtid x WITH (nolock)
                    WHERE  ( x.isincode > ''
                             AND x.isincode = b.breakdowncode )
                            OR ( x.sedolcode > ''
                                 AND x.sedolcode = b.breakdowncode )
                            OR ( x.sedolcode > ''
                                 AND x.sedolcode = b.sedolcode )
                            OR ( x.isincode > ''
                                 AND x.isincode = b.isincode )
                    ORDER  BY CASE
                                WHEN x.sedolcode = b.breakdowncode THEN 1
                                WHEN x.isincode = b.breakdowncode THEN 2
                                WHEN x.sedolcode = b.sedolcode THEN 3
                                WHEN x.isincode = b.isincode THEN 4
                                ELSE 5
                              END,
                              classificationdate DESC) k 

Plano de execução

insira a descrição da imagem aqui

Order Bydentro do Cross Applyé muito caro, existe alguma maneira melhor de escrever essa consulta?

sql-server t-sql
  • 1 1 respostas
  • 6449 Views

1 respostas

  • Voted
  1. Best Answer
    Joe Obbish
    2017-06-21T17:54:18+08:002017-06-21T17:54:18+08:00

    Você pode eliminar a classificação, se desejar, embora seja difícil dizer se isso melhorará o desempenho da consulta. A chave é como você construiu sua ORDER BYcláusula junto com as condições de pesquisa. Se houver alguma linha que corresponda x.sedolcode = b.breakdowncode, você deseja pegar essa linha, caso contrário, você vai para a próxima condição. Com os índices corretos, podemos evitar a classificação dividindo os arquivos APPLY. O otimizador de consulta do SQL Server realmente dá uma boa dica porque transforma suas ORcondições em UNIONs.

    Vou criar um exemplo limitado para mostrar a forma geral do plano de consulta que procuro. Também assumirei que a PfPortfolioHoldingClassificationFtidtabela tem uma chave primária e uma chave de cluster em uma PKcoluna. Aqui estão meus dados de teste:

    CREATE TABLE #BreakdownSet (
        BreakdownClassificationId BIGINT NOT NULL,
        breakdowncode VARCHAR(10) NULL,
        sedolcode VARCHAR(10) NULL,
        isincode VARCHAR(10) NULL
    );
    
    INSERT INTO #BreakdownSet
    SELECT 
      t.RN
    , CASE WHEN RN % 10 = 1 THEN t.RN ELSE NULL END
    , CASE WHEN RN % 10 = 4 THEN t.RN ELSE NULL END
    , CASE WHEN RN % 10 = 7 THEN t.RN ELSE NULL END
    FROM
    (
        SELECT TOP (1500000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
        FROM master..spt_values t1
        CROSS JOIN master..spt_values t2
    ) t;
    
    CREATE TABLE dbo.PfPortfolioHoldingClassificationFtid (
        PK BIGINT NOT NULL,
        isincode VARCHAR(10) NOT NULL,
        sedolcode VARCHAR(10) NOT NULL,
        ClassificationDate DATE NOT NULL,
        OTHER_COLUMN VARCHAR(200) NOT NULL,
        PRIMARY KEY (PK)
    );
    
    INSERT INTO dbo.PfPortfolioHoldingClassificationFtid WITH (TABLOCK)
    SELECT 
      t.RN
    , t.RN
    , t.RN
    , DATEADD(DAY, t.rn / 100, '20170101')
    , REPLICATE('OTHER', 40)
    FROM
    (
        SELECT TOP (1500000) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
        FROM master..spt_values t1
        CROSS JOIN master..spt_values t2
    ) t;
    
    CREATE INDEX isin_date ON dbo.PfPortfolioHoldingClassificationFtid (isincode, ClassificationDate);
    
    CREATE INDEX sedol_date ON dbo.PfPortfolioHoldingClassificationFtid (sedolcode, ClassificationDate);
    

    Aqui está sua consulta com minhas definições de tabela:

    SELECT b.breakdownclassificationid, 
           k.isincode, 
           k.sedolcode, 
           classificationdate, 
           other_column 
    FROM   #breakdownset b 
           OUTER apply (SELECT TOP 1 isincode, 
                                     sedolcode, 
                                     classificationdate, 
                                     other_column 
                        FROM   dbo.pfportfolioholdingclassificationftid x WITH ( 
                               nolock) 
                        WHERE  ( x.isincode > '' 
                                 AND x.isincode = b.breakdowncode ) 
                                OR ( x.sedolcode > '' 
                                     AND x.sedolcode = b.breakdowncode ) 
                                OR ( x.sedolcode > '' 
                                     AND x.sedolcode = b.sedolcode ) 
                                OR ( x.isincode > '' 
                                     AND x.isincode = b.isincode ) 
                        ORDER  BY CASE 
                                    WHEN x.sedolcode = b.breakdowncode THEN 1 
                                    WHEN x.isincode = b.breakdowncode THEN 2 
                                    WHEN x.sedolcode = b.sedolcode THEN 3 
                                    WHEN x.isincode = b.isincode THEN 4 
                                    ELSE 5 
                                  END, 
                                  classificationdate DESC) k; 
    

    Não surpreendentemente eu recebo um plano diferente do seu, mas o tipo ainda tem um alto custo estimado. E se dividirmos APPLYem quatro partes e cada APPLYuma retornar apenas a chave primária da tabela? Se tivermos um índice de cobertura para cada um APPLY, podemos encontrar a chave primária da linha correspondente com no máximo quatro buscas de índice. Nenhuma classificação é necessária. Também podemos pular as buscas que não precisamos adicionando filtros nos APPLYs, mas isso não é um comportamento garantido. Aqui está uma maneira de escrevê-lo:

    SELECT b.breakdownclassificationid, 
           k.isincode, 
           k.sedolcode, 
           classificationdate, 
           other_column 
    FROM   #breakdownset b 
           OUTER apply (SELECT TOP 1 pk 
                        FROM   dbo.pfportfolioholdingclassificationftid x 
                        WHERE  x.sedolcode = b.breakdowncode 
                        ORDER  BY classificationdate DESC) a1 
           OUTER apply (SELECT TOP 1 pk 
                        FROM   dbo.pfportfolioholdingclassificationftid x 
                        WHERE  x.isincode = b.breakdowncode 
                               AND a1.pk IS NOT NULL 
                        ORDER  BY classificationdate DESC) a2 
           OUTER apply (SELECT TOP 1 pk 
                        FROM   dbo.pfportfolioholdingclassificationftid x 
                        WHERE  x.sedolcode = b.sedolcode 
                               AND a2.pk IS NOT NULL 
                        ORDER  BY classificationdate DESC) a3 
           OUTER apply (SELECT TOP 1 pk 
                        FROM   dbo.pfportfolioholdingclassificationftid x 
                        WHERE  x.isincode = b.isincode 
                               AND a3.pk IS NOT NULL 
                        ORDER  BY classificationdate DESC) a4 
           LEFT OUTER JOIN dbo.pfportfolioholdingclassificationftid k 
                        ON k.pk = COALESCE(a1.pk, a2.pk, a3.pk, a4.pk);
    

    Com 1,5 milhão de linhas na tabela temporária, o pior caso possível deve ser 6 milhões de buscas de índice não clusterizado e 1,5 milhão de buscas de índice clusterizado.

    A consulta é executada em dois segundos na minha máquina. O tempo de execução não importa porque tenho dados sem sentido. No entanto, não há um tipo no plano. Carreguei o plano de consulta para Paste The Plan . Você deve considerar fazer isso também para perguntas futuras. Aqui está também uma captura de tela do plano real:

    hash do plano real

    A consulta que você tem faz uma junção de loop aninhada e não fica paralela. Com LOOP JOINe MAXDOP 1dicas a consulta termina em sete segundos na minha máquina. Aqui está o plano e aqui está uma captura de tela:

    insira a descrição da imagem aqui

    • 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