【问题标题】:Query slow with Order by clause in Range-List Partition Table使用范围列表分区表中的 Order by 子句查询慢
【发布时间】:2014-07-25 18:33:36
【问题描述】:

您好,我用范围列表分区创建了一个 FACT TABLE。

范围分区为月份 DATE_REG ( 01/2013, ... ,01/2014, 02/2014, ....)。 列表子分区用于字符串 TYPE_R('A'、'B'、'C')。

主索引是

在 FACT_TABLE (DATE_REG) 上创建索引 INX_DATE_REG

我的查询是

Select
.... 
FROM FACT_TABLE 
INNER JOIN A ...
INNER JOIN B ...
INNER JOIN C ...
INNER JOIN D ...
INNER JOIN E ...
WHERE DATE_REG >= '01/01/2013' -- DD/MM/YYYY
AND DATE_REG < '01/01/2014'
AND TYPE_R = 'B'
ORDER BY DATE_REG ASC

当我省略 ORDER BY Clause 时,执行时间是 2.35 秒,但是当我考虑 Order By 时,时间更改为 125 秒。

我知道这个问题是因为当order by处于活动状态时,它通过所有行,并且DATE_REG的范围在多个分区中。

我的问题是:如何优化这个查询?

提前致谢。

更新

当我的查询是(案例 1)时:

Select
ft.x,
ft.y,
...
ft.xxxxx
FROM FACT_TABLE ft 
INNER JOIN A ...
INNER JOIN B ...
INNER JOIN C ...
INNER JOIN D ...
INNER JOIN E ...
WHERE DATE_REG >= '01/01/2013' -- DD/MM/YYYY
AND DATE_REG < '01/01/2014'
AND TYPE_R = 'B'
ORDER BY DATE_REG ASC

时间是 15 秒。

当我的查询是(案例 2)时:

Select
ft.x,
ft.y,
...
ft.xxxxx,
E.abc
FROM FACT_TABLE ft 
INNER JOIN A ...
INNER JOIN B ...
INNER JOIN C ...
INNER JOIN D ...
INNER JOIN E ...
WHERE DATE_REG >= '01/01/2013' -- DD/MM/YYYY
AND DATE_REG < '01/01/2014'
AND TYPE_R = 'B'
ORDER BY DATE_REG ASC

时间是 150 秒。 abd 是一个没有索引的列。

当我的查询是(案例 3):

Select
*
FROM FACT_TABLE ft 
INNER JOIN A ...
INNER JOIN B ...
INNER JOIN C ...
INNER JOIN D ...
INNER JOIN E ...
WHERE DATE_REG >= '01/01/2013' -- DD/MM/YYYY
AND DATE_REG < '01/01/2014'
AND TYPE_R = 'B'
ORDER BY DATE_REG ASC

时间是 17 秒。

当查询从另一个表调用额外的列时排序变慢,但是当我调用所有列(案例 3)时,时间小于案例 2。

解释计划_案例1

解释计划 _ 案例 2

此时每个分区包含 250 万行。

【问题讨论】:

  • “seg”是“seconds”的缩写吗(通常缩写为“sec”)?您是否正在测量获取第一行所需的时间?或者获取最后一行所需的时间?您的查询返回多少行?
  • 对不起,我更正了。我的测试是针对第一行的。大约有 8000/16000000 行。我刚刚添加了新信息。谢谢
  • 测量获取第一行所需的时间会使比较不合理。为了在您指定order by 时返回第一行,需要获取所有行并对其进行排序。为了返回没有order by 的第一行,Oracle 不需要首先具体化结果集。但是,您发布的三个查询中没有一个缺少order by。查询 1 和 2 似乎相同。查询 3 似乎仅在 select 列表中的列列表中有所不同。这真的是唯一的区别吗?
  • 是的,唯一的区别是在另一个表中添加不是外键的列时,第二次查询会变慢。你的问题是,是否有可能只添加一列随着时间的推移而发生很大变化?当我查阅所有列时,时间比特定列时短。

标签: oracle oracle11g query-optimization


【解决方案1】:

您的where 子句对我来说没有意义:

WHERE DATE_REG >= '01/01/2013' AND -- DD/MM/YYYY
      DATE_REG >= '01/11/2013' AND
      TYPE_R = 'B'
ORDER BY DATE_REG ASC

这相当于:

WHERE DATE_REG >= '01/11/2013' AND
      TYPE_R = 'B'
ORDER BY DATE_REG ASC

我对使用“DD/MM/YYYY”格式感到不舒服,所以我认为这会更好地表达为:

WHERE DATE_REG >= to_date('01/11/2013', 'DD/MM/YYYY') AND
      TYPE_R = 'B'
ORDER BY DATE_REG ASC

至于您使用order by 查询的性能,可能是因为数据量大。排序确实需要时间,目前尚不清楚在这种情况下如何安排 Oracle 使用索引。

【讨论】:

  • 抱歉,第二个约束是 AND DATE_REG
  • @JohnPortella。 . .您仍然没有使用 Oracle 的标准日期格式,所以查询对我来说非常可疑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
  • 1970-01-01
  • 2013-07-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多