【问题标题】:Oracle SQL query optimization - getting counts based on a varchar fieldOracle SQL 查询优化 - 基于 varchar 字段获取计数
【发布时间】:2019-02-20 13:53:54
【问题描述】:

优化查询

我有一个查询从一个表中获取数据并从其他两个表中获取两个计数 在 varchar 字段类型上。我需要从 TABLE2 中获取计数,其中 TYPE=TABLE1.TYPE 和 从 TABLE3 开始计数,其中 TYPE=TABLE1.TYPE

此时我无法在这些字段上创建任何索引,因此我决定使用能带来原始查询执行时间的函数 减少到 5 秒,这仍然太多了。有关如何进一步优化我的查询的任何建议?

 SELECT     a.ID, 
    a.FIELD1, 
    a.FIELD2, 
    a.TYPE, 
    GET_COUNT_1(a.TYPE) as COUNT1,
    GET_COUNT_2(a.TYPE) as COUNT2,
FROM TABLE1 a

我原来的查询是:

SELECT  a.ID, 
    a.FIELD1, 
    a.FIELD2, 
    a.TYPE, 
    (SELECT COUNT(*) FROM TABLE2 b WHERE b.TYPE=a.TYPE) as COUNT1,
    (SELECT COUNT(*) FROM TABLE3 c WHERE c.TYPE=a.TYPE) as COUNT2
FROM TABLE1 a

【问题讨论】:

  • 您尝试过使用 JOIN 吗?可以发一下你原来的SQL和时间吗?
  • 对选定的每一行使用一个函数不太可能是最快的方法,因为 SQL 和 PL/SQL 之间的上下文切换。您可以尝试相关的子查询 - 例如(select count(*) from table2 where table2.type=a.type) as count1 - 但加入通常会提供最佳性能。你有关于表格的最新统计信息吗?什么是使用 join 的查询计划?
  • @rs。我添加了我的原始查询,虽然我知道它非常低效
  • @Lord Peter,这正是我之前所做的,花了大约 15 秒。使用功能它下降到 5 秒
  • 两个子查询似乎相同,应该产生相同的计数。这真的是你想要的吗?

标签: sql oracle


【解决方案1】:

如果您在table2(TYPE) 上没有索引,那么使用子查询是致命的,因为您将重复(对于TABLE1 的每一行)执行全表扫描

显然,可以节省您的 Oracle 子查询兑现并没有发挥作用。

函数方式也不会好多少,只是你自己实现一些函数结果缓存。

但是有一个简单的解决方案可以在子查询中预先计算计数并将结果连接到TABLE1

请注意,您只为每种类型计算一次count不是为 TABLE1 的每一行计算一次

with cnt as 
(select type, count(*) cnt
from table2 group by type),
cnt2 as 
    (select type, count(*) cnt
    from table3 group by type)
select a.ID, 
    a.FIELD1, 
    a.FIELD2, 
    a.TYPE,
    b.cnt cnt1
    c.cnt cnt2
from  TABLE1 a 
left outer join cnt b
on a.type = b.type
left outer join cnt2 c
on a.type = c.type

您将以一个FTS 结束每个表、聚合和外连接,这是您需要做的最少操作。

【讨论】:

  • 如何再添加一张表?
  • @CodingDuchess 添加到示例中
【解决方案2】:

对于您的查询,您需要table2(type) 上的索引。

这两个子查询完全一样,除了表别名。如果您确实有两个不同的表,或者如果您使用不同的列,那么您将需要该表达式的适当索引。

【讨论】:

  • 正如我所提到的,很遗憾,我目前无法创建索引
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多