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 / 228041
Accepted
crokusek
crokusek
Asked: 2019-01-25 17:15:08 +0800 CST2019-01-25 17:15:08 +0800 CST 2019-01-25 17:15:08 +0800 CST

Como obter a aplicação cruzada para operar linha por linha em uma exibição?

  • 772

Temos uma visão otimizada para consultas de item único (200ms sem paralelismo):

select * 
    from OptimizedForSingleObjectIdView e2i
   where ObjectId = 3374700

Também funciona em pequenos conjuntos de ids estáticos (~5).

select * 
    from OptimizedForSingleObjectIdView e2i
   where ObjectId in (3374700, 3374710, 3374720, 3374730, 3374740);

No entanto, se os objetos vierem de uma fonte externa, ele gerará um plano lento. O plano de execução mostra que a ramificação de execução para a parte de exibição está ignorando o predicado em ObjectId, enquanto no caso original ele os usa para realizar buscas de índice.

select v.*
  from 
     (
       select top 1 ObjectId from Objects
        where ObjectId % 10 = 0
        order by ObjectId
     ) o  
  join OptimizedForSingleObjectIdView v -- (also tried inner loop join)
    on v.ObjectId = o.ObjectId;

Não queremos investir em "dual" otimizando a visão para casos não singulares. Em vez disso, a solução que "procuramos" é chamar repetidamente a visão uma vez por objeto sem recorrer a um SP .

Na maioria das vezes, a solução a seguir chama a exibição linha por linha. Porém não desta vez e nem mesmo para apenas 1 objeto:

select v.*
  from
     (
       select top 1 ObjectId 
         from Objects 
        where ObjectId % 10 = 0 -- non-trivial predicate
        order by ObjectId
     ) o
   cross apply
    (
      select top 2000000000 *
        from OptimizedForSingleObjectIdView v_
       where ObjectId = o.ObjectId 
       order by v_.SomeField
    ) v;

Ao mesmo tempo, pensei que havia uma alegação de que a aplicação cruzada era garantida para execução de linha por linha quando chama uma UDF, mas isso também falhou:

create function FunctionCallingView(@pObjectId bigint)
returns table
as 
return select *
  from OptimizedForSingleObjectIdView 
 where ObjectId = @pObjectId;             

select v.*
  from
     (
       select top 1 ObjectId 
         from Objects 
        where ObjectId % 10 = 0
        order by ObjectId
     ) o
 cross apply FunctionCallingView(o.ObjectId) v

Adicionar opção (forçar ordem) não ajudou - no entanto, já existem duas dicas de hash na exibição. Removê-los temporariamente não ajudou e retarda o caso único.

Aqui está um trecho do plano estimado para o caso lento baseado em função. A estimativa de 1 linha está correta. Mais à direita (não mostrado) é onde há um predicado de busca que não inclui o resultado 1 superior. Isso parece semelhante a outros casos que temos em que valores de sondagem singulares de buscas de tabela não são usados ​​como predicados de busca em outros lugares.

insira a descrição da imagem aqui

sql-server execution-plan
  • 1 1 respostas
  • 1382 Views

1 respostas

  • Voted
  1. Best Answer
    Paul White
    2019-01-26T01:59:11+08:002019-01-26T01:59:11+08:00

    Não é possível garantir totalmente a avaliação da exibição por linha da consulta externa, sem usar algo que introduza um novo escopo de execução T-SQL, por exemplo, uma BEGIN...ENDfunção com valor de tabela não-inline (multi-statement, ). Este é praticamente o conselho dado em resposta à sua pergunta anterior Como usar dicas de mesclagem para isolar consultas complexas no SQL Server .

    Ao mesmo tempo, pensei que havia uma alegação de que a aplicação cruzada era garantida para execução de linha por linha quando chama uma UDF

    Isso não se aplica a funções com valor de tabela inline , pois a definição é expandida na consulta de chamada antes do início da otimização.


    Dito isto, há algumas coisas que você pode fazer para encorajar fortemente o resultado desejado.

    O plano de execução mostra que a ramificação de execução para a parte da visualização está ignorando o predicado on ObjectIdenquanto no caso original ele os usa para realizar buscas de índice.

    Você espera que os ObjectIdvalores sejam avaliados "dentro da exibição" usando buscas de índice para cada linha de condução. Este é o estilo de execução de junção (aplicação) de loops aninhados correlacionados. Observe que o uso do APPLYelemento de linguagem T-SQL não garante que a execução física use o estilo apply.

    Parece que o SQL Server está optando por executar com os ObjectIdvalores testados no operador Nested Loops Join . Este é um padrão de execução de junção de loops aninhados não correlacionados ou ingênuos.

    Provavelmente, isso é causado pelas dicas de junção que você está usando dentro da exibição. As dicas de junção geralmente devem ser evitadas, porque restringem muito a liberdade do otimizador, e não apenas para o tipo físico de junção. Em particular, as dicas de junção também forçam a ordem das junções para toda a consulta (como se você tivesse usado uma FORCE ORDERdica) e impedem várias otimizações relacionadas ao posicionamento e estratégia de agregação e muito mais.

    Se você realmente precisa ter dicas de junção dentro de uma visão (algo que eu sugiro fortemente que você evite em geral), você pode achar que a maneira mais confiável de obter a forma do plano que você deseja é:

    1. Crie uma função em linha ( RETURNS TABLE) usando a definição de exibição (não referenciando a exibição).
    2. Forneça @ObjectIdcomo parâmetro para a função.
    3. Colocar um predicado usando o parâmetro dentro do corpo da função de uma maneira que torne uma busca de índice mais provável.
    4. Uma FORCESEEKdica de tabela dentro da função pode ser usada se realmente todo uso resultar em uma busca.
    5. Chame a nova função inline usando APPLY.

    Eu geralmente não gosto de usar sintaxes e dicas específicas na tentativa de forçar uma certa forma de plano físico. Você pode ter um sucesso mais geral parametrizando as consultas e garantindo a forma do plano usando um guia de plano.

    • 10

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