oracle中简单选择查询的优化

oracle中简单选择查询的优化,oracle,optimization,Oracle,Optimization,我正在尝试优化以下查询: SELECT tickstime AS time, quantity1 AS turnover FROM cockpit_test.ticks WHERE date_id BETWEEN 20111104 AND 20111109 AND mdc_id IN (297613) ORDER BY time; 它非常简单,但运行大约需要60-90秒驾驶舱测试。刻度表格包含超过100米的行。它还有一个索引,

我正在尝试优化以下查询:

 SELECT   tickstime AS time,
          quantity1 AS turnover
    FROM   cockpit_test.ticks
   WHERE   date_id BETWEEN 20111104 AND 20111109 
     AND   mdc_id IN (297613)
ORDER BY   time;
它非常简单,但运行大约需要60-90秒驾驶舱测试。刻度表格包含超过100米的行。它还有一个索引,按MDC\u IDDATE\u ID

解释计划给出以下输出

"-------------------------------------------------------------------------------------------------------"
"| Id  | Operation                    | Name           | Rows  | Bytes |TempSpc| Cost (%CPU)| Time     |"
"-------------------------------------------------------------------------------------------------------"
"|   0 | SELECT STATEMENT             |                | 26905 |   604K|       | 11783   (1)| 00:02:22 |"
"|   1 |  SORT ORDER BY               |                | 26905 |   604K|   968K| 11783   (1)| 00:02:22 |"
"|   2 |   TABLE ACCESS BY INDEX ROWID| TICKS          | 26905 |   604K|       | 11596   (1)| 00:02:20 |"
"|*  3 |    INDEX RANGE SCAN          | TICKS_MDC_DATE | 26905 |       |       |    89   (0)| 00:00:02 |"
"-------------------------------------------------------------------------------------------------------"
" "
"Predicate Information (identified by operation id):"
"---------------------------------------------------"
" "
"   3 - access(""MDC_ID""=297613 AND ""DATE_ID"">=20111104 AND ""DATE_ID""<=20111109)"
表中有3个索引:

  • MDC_ID上的索引
  • 日期ID、MDC ID和时间的复合索引
  • 日期ID、MDC ID上的复合索引

一般来说,Oracle不能组合两个单独的索引(除非它们是位图索引而不是“普通”的btree索引)

什么是
mdc\u id
列?如果有许多不同的值,您可以在
mdc\u id,date\u id
上创建一个复合索引

从理论上讲,Oracle可以使用索引返回已排序的数据。在这种情况下,您的索引应该位于
mdc\u id、date\u id、time


为什么不为日期列使用日期数据类型?对于这个特定的查询,它可能不会有太大的区别,但一般来说,如果使用正确的数据类型,Oracle将能够更好地确定数据的分布。

我将检查此解释计划是否对基数进行了准确的估计。当提供多个谓词时,基数估计得很差是很典型的,而且对于这样一个小的查询和估计的排序大小,执行时间似乎很长(除非您的存储基础结构的能力严重不足,这也是很典型的)

给定查询的持续时间,我将通过调用动态采样来确保估计是准确的

SELECT
  /*+ dynamic_sampling(4) */
  tickstime AS time,
  quantity1 AS turnover
FROM
  cockpit_test.ticks
WHERE
  date_id BETWEEN 20111104 AND 20111109 and
  mdc_id IN (297613)
ORDER BY
 tickstime;

如果估计的临时空间小于realtiy(您可以通过查询V$SQL\u WORKAREA\u ACTIVE来检查这一点),那么您可能必须调整会话的内存设置,以切换到自动内存管理并增加排序区域的大小。

是否可以显示表定义?键、索引“按时间排序”,还是应该是“按时间排序”?我喜欢三列索引的想法,但因为日期id谓词基于一个范围,我认为它不太可能工作,因为索引顺序与请求的顺序不同——(201111041234)将出现在(201111070932)之前。不过,它适用于单个日期id值,这可能很有用。TICKS\u MDC\u date index是一个基于MDC\u id、date\u id的复合索引。还存在一个基于date\u id、MDC\u id和time的复合索引。关于数据类型,我所能说的是,我们使用的是一个遗留数据库,其中有很多奇怪的东西,这是我们必须适应的:(除了数据库调优之外,我们无能为力,所以将此答案标记为已接受。谢谢!
SELECT
  /*+ dynamic_sampling(4) */
  tickstime AS time,
  quantity1 AS turnover
FROM
  cockpit_test.ticks
WHERE
  date_id BETWEEN 20111104 AND 20111109 and
  mdc_id IN (297613)
ORDER BY
 tickstime;