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 / 72094
Accepted
JohnLBevan
JohnLBevan
Asked: 2014-07-23 10:43:28 +0800 CST2014-07-23 10:43:28 +0800 CST 2014-07-23 10:43:28 +0800 CST

Desempenho da verificação de dados em tabelas relacionadas

  • 772

NB: esta questão é puramente acadêmica / para ajudar a melhorar minha compreensão do desempenho do SQL Server.

Dada uma tabela mestre relacionada a uma ou mais outras tabelas, como você determinaria a melhor abordagem para consultar essa tabela mestre em busca de registros, que incluem um indicador para a presença de registros nas tabelas relacionadas?

Por exemplo, digamos que temos uma tabela Pessoa e desejamos obter uma lista de todas as pessoas junto com um indicador de se elas têm filhos (neste exemplo, Pessoa pode ser reutilizada como a tabela relacionada):

create table Person
(
    Id bigint not null constraint pk_Person primary key clustered
    , ParentId bigint null constraint fk_Person_Parent foreign key references Person(Id)
    , FirstName nvarchar(256) not null
    , LastName nvarchar(256) not null
)

Poderíamos executar qualquer uma das consultas abaixo para verificar a presença de filhos relacionados:

--variables for restricting our result set, just to keep things interesting
declare @LastName nvarchar(256) = 'Be%'
, @FirstName nvarchar(256) = null

Exemplo 1

--  fairly straight forward, but requires grouping to account for the 
--  potential of a parent having multiple kids (which I don't care about here)
--  which could be adding some inefficiency.
select parent.Id
, parent.FirstName
, parent.LastName
, case when max(child.Id) is null then 0 else 1 end HasChildren
from Person parent
left outer join Person child --1:n
on child.ParentId = parent.Id
where (@LastName is null or parent.LastName like @LastName)
and (@FirstName is null or parent.FirstName like @FirstName)
group by parent.Id, parent.FirstName, parent.LastName --resolve 1:n

exemplo 2

--  avoid the need to group the results by first getting 
--  a single child per parent.
--  may be inefficient because we get children for all parents
--  even if we filter for only a few parents.
select parent.Id
, parent.FirstName
, parent.LastName 
, coalesce(child.hasChildren, 0) HasChildren
from Person parent
left outer join --1:? (0 or 1)
(
    select distinct parentId, 1 hasChildren
    from Person 
    where parentId is not null --not sure if this adds value
) child 
on child.ParentId = parent.Id
where (@LastName is null or LastName like @LastName)
and (@FirstName is null or FirstName like @FirstName)
--group by removed since we're 1:?

exemplo 3

--  same as #2 except we limit the child results to those 
--  related to the parents we're interested in / having stored
--  them in a CTE to avoid querying for the same parent data 
--  in the inner query and outer query.
--  Getting a bit silly now, but could overcome some inefficienies?
;with parentCTE as (
    select Id, FirstName, LastName 
    from person 
    where (@LastName is null or LastName like @LastName)
    and (@FirstName is null or FirstName like @FirstName)
)
select parentCTE.Id
, parentCTE.FirstName
, parentCTE.LastName 
, coalesce(child.hasChildren, 0) HasChildren
from parentCTE
left outer join --1:? (0 or 1)
(
    select distinct parentId, 1 hasChildren
    from Person 
    where parentId in --reduce the amount of data we return here based on the records we're interested in
    (
        select Id
        from parentCTE
    )
) child 
on child.ParentId = parentCTE.Id

exemplo 4

--  back to a simple one; just check for children on our parents 
--  but this time having brought back the full parent set.
--  may be inefficient because we're querying the table once per 
--  matching parent to check for children.
select parent.Id
, parent.FirstName
, parent.LastName
, coalesce((select top 1 1 from Person child where child.parentId = parent.Id),0) HasChildren
from Person parent
where (@LastName is null or LastName like @LastName)
and (@FirstName is null or FirstName like @FirstName)

Estou atrás de informações sobre como entender melhor as compensações envolvidas em tais situações, em vez de um simples example 3melhor. Indicações para artigos que possam me ajudar a entender também seriam bem-vindas.

SQL Fiddle relacionado: http://sqlfiddle.com/#!6/edc17/3

sql-server performance
  • 1 1 respostas
  • 550 Views

1 respostas

  • Voted
  1. Best Answer
    stacylaray
    2014-07-23T21:40:02+08:002014-07-23T21:40:02+08:00

    O exemplo 4 tem o menor número de varreduras e lê:

    Exemplo 1

    Tempo de análise e compilação do SQL Server: tempo
        de CPU = 4 ms, tempo decorrido = 4 ms.

    Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.

    example1    Id    FirstName       
    -----------------------------
    1           2     Aaron           
    1           3     John            
    1           8     Aaron           
    1           9     John            
    1           14    Aaron           
    1           15    John            
    1           20    Aaron           
    1           21    John            
    

    (8 linhas afetadas)

    Tabela 'Pessoa'.
    Contagem de varredura 9, leituras lógicas 27, leituras físicas 0,

    Rows                 Executes             StmtText                
    -------------------- -------------------- ------------------------
    8                    1                    select 1 example1
    
    , parent.Id
    , parent.FirstName
    , parent.LastName
    , case when max(child.Id) is null then 0 else 1 end HasChildren
    from Person parent
    left outer join Person child 
    on child.ParentId = parent.Id
    where (@LastName is null or parent.Las 1           1           0   
    0       0     |--Compute Scalar(DEFINE:([Expr1005]=(1), [Expr1
    8       1          |--Nested Loops(Left Outer Join, OUTER REFE
    8       1               |--Clustered Index Scan(OBJECT:([sub].
    3       8               |--Stream Aggregate(DEFINE:([Expr1004]
    7       8                    |--Clustered Index Scan(OBJECT:([
    

    (6 linhas afetadas)

    Tempos de execução do SQL Server:
        tempo de CPU = 0 ms, tempo decorrido = 0 ms.

    Exemplo 2

    Tempo de análise e compilação do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 4 ms.

    Tempos de execução do SQL Server:
        tempo de CPU = 0 ms, tempo decorrido = 0 ms.

    example2  Id   FirstName                                            
    ----------------------------
    2         2    Aaron                                                     
    2         3    John                                                      
    2         8    Aaron                                                     
    2         9    John                                                      
    2         14   Aaron                                                     
    2         15   John                                                      
    2         20   Aaron                                                     
    2         21   John         
    

    (8 linhas afetadas)

    Tabela 'Pessoa'.
    Contagem de varredura 9, leituras lógicas 27, leituras físicas 0,

    Rows   Executes   StmtText                                         
    ------ ---------- -----------------------
    8      1          select 2 example2
    
    , parent.Id
    , parent.FirstName
    , parent.LastName 
    , coalesce(child.hasChildren, 0) HasChildren
    from Person parent
    left outer join 
    (
        select distinct parentId, 1 hasChildren
        from Person 
        where parentId is not null 
    ) child 
    
     1           1           0           NULL                          
    0     0       |--Compute Scalar(DEFINE:([Expr1007]=(2), [Expr1
    8     1            |--Nested Loops(Left Outer Join, OUTER REFE
    8     1                 |--Clustered Index Scan(OBJECT:([sub].
    3     8                 |--Stream Aggregate(DEFINE:([Expr1006]
    0     0                      |--Compute Scalar(DEFINE:([Expr10
    7     8                           |--Clustered Index Scan(OBJE
    

    (7 linhas afetadas)

    Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.

    Exemplo 3

    Tempo de análise e compilação do SQL Server: tempo de CPU = 7 ms, tempo decorrido = 7 ms.

    Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.

    example3 Id   FirstName                                            
    ---- ------ ------------------------
    3    2      Aaron                                                  
    3    3      John                                                   
    3    8      Aaron                                                  
    3    9      John                                                   
    3    14     Aaron                                                  
    3    15     John                                                   
    3    20     Aaron                                                  
    3    21     John   
    

    (8 linhas afetadas)

    Tabela 'Pessoa'. Contagem de varredura 9, leituras lógicas 41, leituras físicas 0, r

    Rows     Executes   StmtText                                       
    ------   ---------  ------------------
    8        1          with parentCTE as (
        select Id, FirstName, LastName 
        from person 
        where (@LastName is null or LastName like @LastName)
        and (@FirstName is null or FirstName like @FirstName)
    )
    select 3 example3
    , parentCTE.Id
    , parentCTE.FirstName
    , parentCTE.La 1           1           0           NULL            
    0     0     |--Compute Scalar(DEFINE:([Expr1011]=(3), [Expr1
    8     1          |--Nested Loops(Left Outer Join, OUTER REFE
    8     1               |--Clustered Index Scan(OBJECT:([sub].
    3     8               |--Stream Aggregate(DEFINE:([Expr1010]
    0     0                    |--Compute Scalar(DEFINE:([Expr10
    7     8                         |--Nested Loops(Inner Join, 
    7     8                              |--Clustered Index Scan
    7     7                              |--Clustered Index Seek
    

    (9 linhas afetadas)

    Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.

    Exemplo 4

    Tempo de análise e compilação do SQL Server: tempo de CPU = 3 ms, tempo decorrido = 3 ms.

    Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.

    example4 Id  FirstName                                             
    ---- ----- -------------
    4    2     Aaron        
    4    3     John         
    4    8     Aaron        
    4    9     John         
    4    14    Aaron        
    4    15    John         
    4    20    Aaron        
    4    21    John         
    

    (8 linhas afetadas)

    Tabela 'Pessoa'. Contagem de varredura 3, leituras lógicas 26, leituras físicas 0,

    Rows     Executes   StmtText             
    -------- ---------- ---------------------
    8        1          select 4 example4
    , parent.Id
    , parent.FirstName
    , parent.LastName
    , coalesce((select top 1 1 from Person child where child.parentId =
    from Person parent
    where (@LastName is null or LastName like @LastName)
    and (@FirstName  1           1           0           NULL          
    0       0     |--Compute Scalar(DEFINE:([Expr1002]=(4), [Expr1
    8       1          |--Nested Loops(Left Outer Join, PASSTHRU:(
    8       1               |--Nested Loops(Left Outer Join, OUTER
    8       1               |    |--Clustered Index Scan(OBJECT:([
    0       0               |    |--Compute Scalar(DEFINE:([Expr10
    3       8               |         |--Top(TOP EXPRESSION:((1)))
    3       8               |              |--Clustered Index Scan
    0       0               |--Compute Scalar(DEFINE:([Expr1008]=(
    3       3                    |--Top(TOP EXPRESSION:((1)))     
    3       3                         |--Clustered Index Scan(OBJE
    

    (11 linhas afetadas)

    Tempos de execução do SQL Server: tempo de CPU = 0 ms, tempo decorrido = 0 ms.

    Você quer o menor número possível de varreduras. Quanto mais vezes tivermos que escanear a tabela, mais tempo levará.

    • 3

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