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 / 192686
Accepted
Philip
Philip
Asked: 2017-12-09 00:43:31 +0800 CST2017-12-09 00:43:31 +0800 CST 2017-12-09 00:43:31 +0800 CST

Obtendo um SEEK em vez de SCAN em um agregado

  • 772

Isso está fazendo minha cabeça, mas estou preso em tentar obter um Index Seek no agregado MAX dentro desta consulta.

Aqui está o plano de execução - e estou me perguntando o que estou perdendo aqui, pois atualmente a consulta leva 3/4 segundos para ser concluída, o que é muito lento. Eu indexei em StartDate, ClientID sem sorte.

CREATE TABLE #SearchWords
(
    ID int IDENTITY(1,1),
    Word NVARCHAR(50)
)

INSERT INTO #SearchWords
(
    Word
)
SELECT 
    value 
FROM 
    STRING_SPLIT(@SearchWords, ' ')  
WHERE 
    TRIM(value) <> '' 

SELECT
    C.ClientID, 
    C.FirstName,
    C.LastName,
    C.FullName, 
    C.DateOfBirth,
    G.GenderName, 
    G.GenderIcon, 
    C.VerificationCode,
    MAX(V.StartDate) as LastVisitDate
FROM 
    Client C
LEFT JOIN Visit V on 
    C.ClientID = V.ClientID
INNER JOIN LookUp.Gender G on
    C.GenderID = G.GenderID
WHERE
    (
        EXISTS( -- if we have words
                SELECT *
                FROM #SearchWords s
                WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
                    OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
                    OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
            )
        OR
        (SELECT COUNT(*) FROM #SearchWords)=0 -- if we haven't any words
    )
    AND DateOfBirth BETWEEN ISNULL(@LowerDate,DateOfBirth) AND ISNULL(@UpperDate,DateOfBirth)
GROUP BY
    C.ClientID, 
    C.FirstName,
    C.LastName,
    C.FullName, 
    C.DateOfBirth,
    G.GenderName, 
    G.GenderIcon, 
    C.VerificationCode 
sql-server azure-sql-database
  • 1 1 respostas
  • 58 Views

1 respostas

  • Voted
  1. Best Answer
    Kent Chenery
    2017-12-09T01:14:18+08:002017-12-09T01:14:18+08:00

    Você deseja que seu índice tenha ClientID como a chave principal. Por exemplo:

    CREATE INDEX IX_Visit_ClientID_StartDate ON Visit(ClientID, StartDate)

    Isso ocorre porque você precisa ingressar no ClientID antes de encontrar a StartDate mais recente. Portanto ClientID precisa aparecer primeiro.

    Junto com essa mudança de índice... Como você só quer encontrar o mais recente Visit.StartDate , você pode mudar o seu LEFT JOIN Visitpara um OUTER APPLYque obtenha a data mais recente.

    Tente isto:

    CREATE TABLE #SearchWords
    (
        ID int IDENTITY(1,1),
        Word NVARCHAR(50)
    )
    
    DECLARE @SearchWordCount INTEGER;
    
    INSERT INTO #SearchWords
    (
        Word
    )
    SELECT 
        value 
    FROM 
        STRING_SPLIT(@SearchWords, ' ')  
    WHERE 
        TRIM(value) <> ''
    
    SELECT @SearchWordCount = @@ROWCOUNT;
    
    SELECT
        C.ClientID, 
        C.FirstName,
        C.LastName,
        C.FullName, 
        C.DateOfBirth,
        G.GenderName, 
        G.GenderIcon, 
        C.VerificationCode,
        V.LastVisitDate
    FROM 
        Client C
    OUTER APPLY (
        SELECT MAX(StartDate) AS LastVisitDate
        FROM Visit AS V
        WHERE C.ClientID = V.ClientID
    ) AS V
    INNER JOIN LookUp.Gender G on
        C.GenderID = G.GenderID
    WHERE
        (
            EXISTS( -- if we have words
                    SELECT *
                    FROM #SearchWords s
                    WHERE (c.FirstName LIKE CONCAT('%',s.Word,'%'))
                        OR (c.LastName LIKE CONCAT('%',s.Word,'%'))
                        OR (c.VerificationCode LIKE CONCAT('%',s.Word,'%'))
                )
            OR @SearchWordCount = 0
        )
        AND DateOfBirth BETWEEN ISNULL(@LowerDate,DateOfBirth) AND ISNULL(@UpperDate,DateOfBirth)
    GROUP BY
        C.ClientID, 
        C.FirstName,
        C.LastName,
        C.FullName, 
        C.DateOfBirth,
        G.GenderName, 
        G.GenderIcon, 
        C.VerificationCode 
    

    Observação:

    Também fiz a @@ROWCOUNTmelhoria que sugeri no meu comentário.

    O GROUP BYé quase certamente desnecessário agora também. Remova-o se estiver.

    Fora do assunto:

    Um último comentário final que tecnicamente não está relacionado à sua pergunta. Você parece estar fazendo algo para o qual a pesquisa de texto completo pode ser uma solução melhor.

    • 1

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