Sybase ASE:优化具有多个子查询的查询
Sybase ASE: Optimizing a query with multiple subqueries
我有一个大型 table(large_table,超过 600 万行),其中包含索引列
- id主键
- small_ref_id(整数)引用小table(small_table,2k+行)
的主键
mid_ref_id(整数)引用一个介质的主键table(mid_table,200k+行)
small_table 的数据除以索引列 group_name (varchar) 中命名的数据组。
mid_table的数据按索引列类型(varchar)命名的数据类型划分。
大 table 有 2 个索引时间戳(date_time1,date_time2)。
- 媒体 table 有 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'))
获取结果可能需要几分钟(<5 分钟)。
我尝试了什么:
- 将 small_ref_id 的查询拆分为与 'MyGroup'、运行 中的 id 一样多的查询并行(使用应用程序内部的线程池,具有固定数量的工作线程) : 这导致没有任何改善,加上 100% 的数据库 CPU.
- 用 "exists (select 1 from large_table t where t.id=large_table.id" 替换 "large_table.id in (select id from large_table" :这也没有改善。
有什么想法吗?
在我看来你不需要子查询。您可以将这三个条件应用于主查询中已有的 large_table
和 mid_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.
注意:你确定最后一个条件吗?它在 mid_table.date_time3
上测试,而其他两个条件的日期来自 large_table
...
我有一个大型 table(large_table,超过 600 万行),其中包含索引列
- id主键
- small_ref_id(整数)引用小table(small_table,2k+行) 的主键
mid_ref_id(整数)引用一个介质的主键table(mid_table,200k+行)
small_table 的数据除以索引列 group_name (varchar) 中命名的数据组。
mid_table的数据按索引列类型(varchar)命名的数据类型划分。
大 table 有 2 个索引时间戳(date_time1,date_time2)。
- 媒体 table 有 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'))
获取结果可能需要几分钟(<5 分钟)。
我尝试了什么:
- 将 small_ref_id 的查询拆分为与 'MyGroup'、运行 中的 id 一样多的查询并行(使用应用程序内部的线程池,具有固定数量的工作线程) : 这导致没有任何改善,加上 100% 的数据库 CPU.
- 用 "exists (select 1 from large_table t where t.id=large_table.id" 替换 "large_table.id in (select id from large_table" :这也没有改善。
有什么想法吗?
在我看来你不需要子查询。您可以将这三个条件应用于主查询中已有的 large_table
和 mid_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.
注意:你确定最后一个条件吗?它在 mid_table.date_time3
上测试,而其他两个条件的日期来自 large_table
...