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 / 172521
Accepted
Kshitiz Sharma
Kshitiz Sharma
Asked: 2017-05-03 06:07:12 +0800 CST2017-05-03 06:07:12 +0800 CST 2017-05-03 06:07:12 +0800 CST

Diferença entre a visualização inline e a cláusula WITH?

  • 772

As visualizações embutidas permitem que você selecione uma subconsulta como se fosse uma tabela diferente:

SELECT
    *
FROM /* Selecting from a query instead of table */
    (
        SELECT
            c1
        FROM
            t1
        WHERE
            c1 > 0
    ) a
WHERE
    a.c1 < 50;

Eu vi isso usando termos diferentes: visualizações inline, cláusula WITH, CTE e tabelas derivadas. Para mim, parece que eles são sintaxe específica de fornecedor diferente para a mesma coisa.

Esta é uma suposição errada? Existem diferenças técnicas/de desempenho entre eles?

oracle cte
  • 5 5 respostas
  • 29582 Views

5 respostas

  • Voted
  1. Best Answer
    a1ex07
    2017-05-03T06:58:31+08:002017-05-03T06:58:31+08:00

    Existem algumas diferenças importantes entre as visualizações inline (tabelas derivadas) e a cláusula WITH (CTE) no Oracle. Alguns deles são bastante universais, ou seja, são aplicáveis ​​a outros RDBMS.

    1. WITHpode ser usado para construir subconsultas recursivas, inline view -not (até onde eu sei, o mesmo é para todos os RDBMS que suportam CTE)
    2. É mais provável que a subconsulta na WITHcláusula seja executada fisicamente primeiro; em muitos casos, escolher entre WITHuma visualização em linha faz com que o otimizador escolha diferentes planos de execução (acho que é específico do fornecedor, talvez até específico da versão).
    3. A subconsulta WITHpode ser materializada como uma tabela temporária (não sei se algum outro fornecedor além da Oracle oferece suporte a esse recurso).
    4. A subconsulta em WITHpode ser referenciada várias vezes, em outras subconsultas e na consulta principal (verdadeiro para a maioria dos RDBMS).
    • 11
  2. Joe Obbish
    2017-05-03T13:54:41+08:002017-05-03T13:54:41+08:00

    Outras respostas cobrem muito bem as diferenças de sintaxe, então não vou entrar nisso. Em vez disso, esta resposta cobrirá apenas o desempenho no Oracle.

    O otimizador Oracle pode optar por materializar os resultados de um CTE em uma tabela temporária interna. Ele usa uma heurística para fazer isso em vez de otimização baseada em custo. A heurística é algo como "Materialize o CTE se não for uma expressão trivial e o CTE for referenciado mais de uma vez na consulta". Existem algumas consultas para as quais a materialização melhorará o desempenho. Existem algumas consultas para as quais a materialização degradará drasticamente o desempenho. O exemplo a seguir é um pouco artificial, mas ilustra bem o ponto:

    Primeiro crie uma tabela com uma chave primária que contenha inteiros de 1 a 10000:

    CREATE TABLE N_10000 (NUM_ID INTEGER NOT NULL, PRIMARY KEY (NUM_ID));
    
    INSERT /*+APPEND */ INTO N_10000
    SELECT LEVEL
    FROM DUAL
    CONNECT BY LEVEL <= 10000
    ORDER BY LEVEL;
    
    COMMIT;
    

    Considere a seguinte consulta que usa duas tabelas derivadas:

    SELECT t1.NUM_ID
    FROM 
    (
      SELECT n1.NUM_ID
      FROM N_10000 n1
      CROSS JOIN N_10000 n2
    ) t1
    LEFT OUTER JOIN 
    (
      SELECT n1.NUM_ID
      FROM N_10000 n1
      CROSS JOIN N_10000 n2
    ) t2 ON t1.NUM_ID = t2.NUM_ID
    WHERE t1.NUM_ID <= 0;
    

    Podemos analisar essa consulta e determinar rapidamente que ela não retornará nenhuma linha. A Oracle deve ser capaz de usar o índice para determinar isso também. Na minha máquina, a consulta termina quase instantaneamente com o seguinte plano:

    bom plano

    Eu não gosto de me repetir, então vamos tentar a mesma consulta com um CTE:

    WITH N_10000_CTE AS (
      SELECT n1.NUM_ID
      FROM N_10000 n1
      CROSS JOIN N_10000 n2
    )
    SELECT t1.NUM_ID
    FROM N_10000_CTE t1
    LEFT JOIN N_10000_CTE t2 ON t1.NUM_ID = t2.NUM_ID
    WHERE t1.NUM_ID <= 0;
    

    Aqui está o plano:

    plano ruim

    Esse é um plano muito ruim. Em vez de usar o índice, o Oracle materializa 10.000 X 10.000 = 10.000.000 linhas em uma tabela temporária apenas para retornar 0 linhas. O custo deste plano é em torno de 6 M o que é muito superior ao da outra consulta. A consulta levou 68 segundos para terminar na minha máquina.

    Observe que a consulta pode ter falhado se não houver memória suficiente ou espaço livre no tablespace temporário.

    Eu posso usar a INLINEdica não documentada para impedir que o otimizador materialize o CTE:

    WITH N_10000_CTE AS (
      SELECT /*+ INLINE */ n1.NUM_ID
      FROM N_10000 n1
      CROSS JOIN N_10000 n2
    )
    SELECT t1.NUM_ID
    FROM N_10000_CTE t1
    LEFT JOIN N_10000_CTE t2 ON t1.NUM_ID = t2.NUM_ID
    WHERE t1.NUM_ID <= 0;
    

    Essa consulta é capaz de usar o índice e termina quase instantaneamente. O custo da consulta é o mesmo de antes, 11. Assim, para a segunda consulta, a heurística usada pelo Oracle resultou na escolha de uma consulta com um custo estimado de 6 M em vez de uma consulta com um custo estimado de 11.

    • 11
  3. S3S
    2017-05-03T06:22:42+08:002017-05-03T06:22:42+08:00

    Para SQL Server, WITH CTEespecifica o conjunto de resultados nomeado temporário, mas é necessário apenas para o primeiro arquivo CTE. ou seja

    WITH CTE AS (SELECT .... FROM), 
    CTE2 AS (SELECT .... FROM)
    
    SELECT CTE.Column, CTE2.Column
    FROM CTE
    INNER JOIN CTE2 on CTE.Column = CTE2.Column
    

    Mas esta não é uma subconsulta ou subconsulta correlacionada. Há coisas que você pode fazer com um CTE que você não pode fazer com uma subconsulta no SQL Server, como atualizar as Tabelas referenciadas em um CTE. Aqui está um exemplo de atualização de uma tabela com um CTE.

    Uma subconsulta seria algo como

    SELECT
       C1,
       (SELECT C2 FROM SomeTable) as C2
    FROM Table
    

    Ou uma subconsulta correlacionada é o que você forneceu em seu OP se você fosse referenciar/juntar/limitar seus resultados com base em a.c1.

    Portanto, eles definitivamente não são a mesma coisa, embora em muitos casos você possa usar um ou mais desses métodos para obter o mesmo resultado. Depende apenas de qual é o resultado final.

    • 1
  4. Marko Vodopija
    2017-05-03T07:09:41+08:002017-05-03T07:09:41+08:00

    A principal diferença entre witha cláusula e uma subconsulta no Oracle é que você pode fazer referência a uma consulta dentro da cláusula várias vezes. Você pode fazer algumas otimizações com ele, como transformá-lo em uma tabela temporária usando materializedica. Você também pode fazer consultas recursivas com ele referenciando-se dentro de uma withcláusula. Você não pode fazer isso com uma visualização em linha.

    Mais informações podem ser encontradas aqui e aqui .

    • 1
  5. Justin
    2018-05-17T12:33:41+08:002018-05-17T12:33:41+08:00

    Você precisa ter cuidado com os CTEs no SQL server não apenas no oracle, há casos em que as consultas têm um desempenho muito pior ao usar CTEs em comparação com subconsultas, cross apply, etc.

    Como sempre, é importante testar qualquer consulta sob várias condições de carga para determinar qual delas funciona melhor.

    Semelhante ao @scsimon com oracle, às vezes o servidor MS SQL não faz o que você espera em relação ao uso do índice.

    Se você for usar os mesmos dados mais de uma vez, os CTEs podem ser mais úteis, se você estiver usando apenas uma vez, geralmente uma subconsulta é mais rápida em grandes conjuntos de dados.

    por exemplo, selecione * de (minha subconsulta) junte-se a outra coisa ...

    • 0

relate perguntas

  • Backups de banco de dados no Oracle - Exportar o banco de dados ou usar outras ferramentas?

  • ORDER BY usando prioridades personalizadas para colunas de texto

  • Interface sqlplus confortável? [fechado]

  • Como encontrar as instruções SQL mais recentes no banco de dados?

  • Como posso consultar nomes usando expressões regulares?

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