【问题标题】:Most efficient way to run an encapsulated query运行封装查询的最有效方式
【发布时间】:2014-10-20 03:35:48
【问题描述】:

运行封装在另一个查询中的最有效方法是什么?

1.在查询中查询:

select
  id_user
from table1
where
  foo in (select foo from table2 where dt_signin > '2014-01-01 00:00')

2.通过使用临时表:

create table tmp_table as
select
  foo
from table2
where
  dt_signin > '2014-01-01 00:00'

然后查询临时表

select
  id_user
from table1 t1
join tmp_table tmp
 on t1.foo = tmp.foo

使用method 1where clause 中的查询运行(# rows of table1) 次还是只运行一次并存储在内存中以便与foo 进一步比较?

【问题讨论】:

  • 有一个where exists 子句可能对您有所帮助。另见stackoverflow.com/questions/7471625/…
  • 具有两个查询的解决方案通常比单个查询慢 - 特别是如果第一个查询读取 写入数据。

标签: sql performance postgresql


【解决方案1】:

怎么样:

select
  id_user
from 
  table1 t1
  join (
    select foo from table2 where dt_signin > '2014-01-01 00:00'
  )  t2 ONt1.foo = t2.foo

如果可以使用连接,则无需创建临时表。

【讨论】:

    【解决方案2】:

    exists 变体经常优于其他变体

    select id_user
    from table1
    where exists (
        select 1
        from table2
        where
            dt_signin > '2014-01-01 00:00'
            and
            table1.foo = foo
    )
    

    请注意,外部table1.foo 与子查询中的foo 进行比较

    【讨论】:

      【解决方案3】:

      您的两个查询不做同样的事情。要使第二种方法等效,您需要select distinct:

      select distinct id_user
      from table1 t1 join
           tmp_table tmp
           on t1.foo = tmp.foo;
      

      由于这个额外的操作,我可能期望in 表现更好。但是,一般来说,当您有特定的性能问题时,您应该在系统上的数据上对其进行测试。

      至于您在问题中的疑问,有很多不同的方法可以解决这个问题。以下是一些:

      • 带有in 的子查询
      • 带有joindistinct 的两个表
      • in 的两个表
      • 存在两个表
      • 带有exists 的子查询
      • exists 的两个表
      • CTE 与 join
      • CTE 与in
      • CTE 与exists

      在理想情况下,SQL 编译器会简单地研究查询并获得最佳执行计划,而不管查询是如何表达的。唉,那个世界不是我们生活的世界。

      临时表有时有用(我更喜欢单一查询解决方案)的一个原因是出于优化目的:

      1. 临时表的统计信息是已知的,因此优化器可以选择更好的计划。
      2. 您可以在临时表上构建索引以提高性能。

      您的子查询不是很复杂,所以这些可能不是问题。

      在不同的情况下,不同的方法可能效果更好。默认情况下,我会在tmp_Table(dt_signin, foo) 上建立一个索引并使用exists

      【讨论】:

      • 带有 in 的子查询是否需要对第一个表的每一行执行该子查询? (参考问题中的方法1)
      • @蒂亚戈。 . .我不知道 Postgres 是否总是按顺序执行此类查询。一些数据库可以。其他人使用子查询对in 进行了优化。特定情况的真正答案是使用explain
      猜你喜欢
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-06
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 1970-01-01
      相关资源
      最近更新 更多