Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用大型ish数据集在Oracle DB上的性能不佳_Sql_Oracle - Fatal编程技术网

Sql 使用大型ish数据集在Oracle DB上的性能不佳

Sql 使用大型ish数据集在Oracle DB上的性能不佳,sql,oracle,Sql,Oracle,我正在使用一个旧的Oracle表,该表包含大约30列和15亿行。它包含过去两年的销售数据。该表有关于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 t

我正在使用一个旧的Oracle表,该表包含大约30列和15亿行。它包含过去两年的销售数据。该表有关于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数据库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 |            |
-------------------------------------------------------------------------------------------------------------------------------------

求和要求数据库在显示结果之前读取并处理满足查询条件的所有行,并且优化器似乎认为最具限制性的条件是SALES_DATE。表似乎也是在SALES_DATE进行分区的,这也可能会影响优化器的决策

首先,通过执行以下命令确保表的统计信息是最新的

BEGIN
  DBMS_STATS.GATHER_TABLE_STATS('YOUR_SCHEMA', 'SALES');
END;
SELECT TABLE_NAME, LAST_ANALYZED
  FROM USER_TABLES
  WHERE TABLE_NAME = 'SALES'
您可能需要一个DBA来为您运行这个。希望统计数据已经在您的表中定期收集,所以请与您的DBA联系。您可以通过执行

BEGIN
  DBMS_STATS.GATHER_TABLE_STATS('YOUR_SCHEMA', 'SALES');
END;
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)这允许优化器获取查询所需的所有数据,而无需读取行中的实际数据。这是一个实用的解决方案,可以提高性能,但可能会(轻微地)降低插入和更新的速度


祝你好运。

请按照本帖中的步骤进行操作,并将其与你的问题一起发布;我们需要知道更多。除了人们提到的其他所有内容外,您使用的是什么Oracle版本?你确定这真的是你的工作吗?如果您对数据库的访问权限有限,这表明某个地方有一个DBA团队应该为您进行此类分析和调整。15亿行听起来可能是分区的候选。您能粘贴表和所有索引的完整DDL吗?@user1516873更好的方法是使用一个复合索引[销售日期、客户ID、产品ID]。但需要知道每个字段的选择性及其组合,以便推荐。