【问题标题】:Sybase ASE: Optimizing a query with multiple subqueriesSybase ASE:优化具有多个子查询的查询
【发布时间】:2018-01-13 04:12:04
【问题描述】:

我有一个带有索引列的大表(large_table,6M+ 行)

  • id 主键
  • small_ref_id(整数)引用小表的主键(small_table,2k+行)
  • mid_ref_id(整数)引用中表的主键(mid_table,200k+ 行)

  • small_table 的数据按索引列 group_name (varchar) 中命名的数据组划分。

  • mid_table 的数据按索引列类型(varchar)命名的数据类型划分。

  • 大表有 2 个索引时间戳(date_time1,date_time2)。

  • 中表有 1 个索引时间戳 (date_time3)。

我的查询看起来像:

select * from large_table, mid_table, small_table 
where large_table.small_ref_id=small_table.id
and large_table.mid_ref_id=mid_table.id
and small_table.group_name='MyGroup'
and 
   (large_table.id in (select large_table.id from large_table, mid_table
where mid_table.id=large_table.mid_ref_id 
and large_table.date_time1 between '2010-01-01' and '2017-01-01' 
and mid_table.type='Type1')
or large_table.id in (select large_table.id from large_table, mid_table 
where mid_table.id=large_table.mid_ref_id 
and large_table.date_time2 between '2010-06-01' and '2017-01-01' 
and mid_table.type='Type2')
or large_table.id in (select large_table.id from large_table, mid_table 
where mid_table.id=large_table.mid_ref_id 
and mid_table.date_time3 between '2010-08-01' and '2017-01-01' 
and mid_table.type='Type3'))

获取结果可能需要几分钟(

我尝试了什么:

  • 通过 small_ref_id 将查询拆分为与“MyGroup”内的 id 一样多的查询,并行运行(使用应用程序内的线程池,具有固定数量的工作人员):这导致没有任何改进,而且占用了 100%数据库 CPU。
  • 将 "large_table.id in (select id from large_table" 替换为 "exists (select 1 from large_table t where t.id=large_table.id" :这也没有任何改进。

有什么想法吗?

【问题讨论】:

  • 从不FROM 子句中使用逗号。 始终使用正确、明确的JOIN 语法。
  • 可以分享一下查询计划吗?

标签: sql performance indexing sybase sap-ase


【解决方案1】:

在我看来,您不需要子查询。您可以将这三个条件应用于您已经从主查询中获得的 large_tablemid_table 数据:

select     * 
from       large_table 
inner join mid_table
        on large_table.mid_ref_id = mid_table.id
inner join small_table 
        on large_table.small_ref_id = small_table.id
       and small_table.group_name = 'MyGroup'
where      (
                (large_table.date_time1 between '2010-01-01' and '2017-01-01' 
                 and mid_table.type = 'Type1')
            or
                (large_table.date_time2 between '2010-06-01' and '2017-01-01' 
                 and mid_table.type = 'Type2')
            or  
                (mid_table.date_time3 between '2010-08-01' and '2017-01-01' 
                 and mid_table.type = 'Type3')
           )

附带说明:使用inner join syntax

NB:你确定最后一个条件吗?它在mid_table.date_time3 上进行测试,而其他两个条件的日期来自large_table...

【讨论】:

  • 不使用内连接语法有什么影响?
  • 查询效率应该没有差别。这只是一个语法选择。但是将连接条件放在where 子句中是如此......八十年代?这是关于它的blog
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-13
  • 2014-11-03
  • 1970-01-01
  • 1970-01-01
  • 2014-06-01
  • 2014-03-21
相关资源
最近更新 更多