使用大型数据集的

时间:2015-12-17 10:29:14

标签: sql oracle

我正在使用包含大约30列和15亿行的旧Oracle表。它包含过去两年的销售数据。该表具有SALES_DATE,CLIENT_ID和PRODUCT_ID的索引。我经常需要在两个日期之间找出特定客户的特定产品的销售价值。我经常运行的查询类型为:

select sum(SALES_VALUE) 
from SALES 
where CLIENT_ID = 9999 
  and PRODUCT_ID IN (1, 2, 15, 16) 
  and SALES_DATE between to_date('2015-01-01', 'yyyy-mm-dd')
                     and to_date('2015-02-28', 'yyyy-mm-dd')

此查询的单次运行通常需要半小时(即使选择了相对较短的日期范围),我很难理解原因。查询本身是否有任何特别低效的问题,还是更可能是由于数据库本身存在性能问题? 我改变数据库本身的能力非常有限,但我可以自由编写自己的查询。我该怎么做才能提高性能?

提前致谢, OSF

编辑: 我们使用的是Oracle Database 11g 11.2.0.1.0 以下是解释计划的结果:

PLAN_TABLE_OUTPUT

-------------------------------------------------------------------------------------------------------------------------------------
| Id  | Operation                              | Name          | Rows  | Bytes | Cost  | Pstart| Pstop |    TQ  |IN-OUT| PQ Distrib |
-------------------------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                       |               |     1 |    20 | 11189 |       |       |        |      |            |
|   1 |  SORT AGGREGATE                        |               |     1 |    20 |       |       |       |        |      |            |
|   2 |   PX COORDINATOR                       |               |       |       |       |       |       |        |      |            |
|   3 |    PX SEND QC (RANDOM)                 | :TQ10000      |     1 |    20 |       |       |       |  Q1,00 | P->S | QC (RAND)  |
|   4 |     SORT AGGREGATE                     |               |     1 |    20 |       |       |       |  Q1,00 | PCWP |            |
|   5 |      PX PARTITION RANGE ALL            |               |   157 |  3140 | 11189 |     1 |   160 |  Q1,00 | PCWC |            |
|   6 |       TABLE ACCESS BY LOCAL INDEX ROWID| SALES         |   157 |  3140 | 11189 |     1 |   160 |  Q1,00 | PCWP |            |
|   7 |        INDEX RANGE SCAN                | IX_SALES_DATE |   295K|       |   703 |     1 |   160 |  Q1,00 | PCWP |            |
-------------------------------------------------------------------------------------------------------------------------------------

1 个答案:

答案 0 :(得分:1)

SUM要求数据库在显示结果之前读取并处理满足查询条件的所有行,并且优化程序认为最大限制条件是SALES_DATE。它似乎也在SALES_DATE分区,这也可能影响优化器的决定。

首先,通过执行

确保表的统计信息是最新的
BEGIN
  DBMS_STATS.GATHER_TABLE_STATS('YOUR_SCHEMA', 'SALES');
END;

您可能需要让DBA为您运行此操作。希望您的桌面上已经定期收集统计数据,因此请咨询您的DBA。您可以通过执行

找出上次收集的统计数据
SELECT TABLE_NAME, LAST_ANALYZED
  FROM USER_TABLES
  WHERE TABLE_NAME = 'SALES'

如果这已经过了一段时间(超过几天),或者这是一个高活动表,则可能需要更频繁的统计数据收集。

正如上面评论中提到的,为了提高性能,您可能需要添加索引。您可以在(SALES_DATE,CLIENT_ID,PRODUCT_ID)上添加索引,但仍然需要数据库在扫描索引后读取实际数据行,将所需的I / O加倍,这可能会提示优化器进行表扫描 - 所以如果你是务实的,你可以制作索引(SALES_DATE,CLIENT_ID,PRODUCT_ID,SALES_VALUE),它允许优化器获得查询所需的所有数据而无需读取行中的实际数据。这是一个提高性能的实用解决方案,但可能(通常)减慢INSERT和UPDATE。

祝你好运。