如何使用SELECT DISTINCT提高Oracle的性能
-
20-08-2019 - |
题
我目前在基于OFBiz的ERP部署工作 正在使用的数据库是Oracle 10g企业
一个最大的问题是一些Oracle的性能问题,分析ofbiz的日志,下面的查询:
SELECT DISTINCT ORDER_ID, ORDER_TYPE_ID, ORDER_NAME, EXTERNAL_ID,
SALES_CHANNEL_ENUM_ID, ORDER_DATE, ENTRY_DATE, VISIT_ID, STATUS_ID, CREATED_BY,
FIRST_ATTEMPT_ORDER_ID, CURRENCY_UOM, SYNC_STATUS_ID, BILLING_ACCOUNT_ID,
ORIGIN_FACILITY_ID, WEB_SITE_ID, PRODUCT_STORE_ID, TERMINAL_ID, TRANSACTION_ID,
AUTO_ORDER_SHOPPING_LIST_ID, NEEDS_INVENTORY_ISSUANCE, IS_RUSH_ORDER, INTERNAL_CODE,
REMAINING_SUB_TOTAL, GRAND_TOTAL, LAST_UPDATED_STAMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP,
CREATED_TX_STAMP, RECIBIR_BODEGAL, RECEPCIONADA_BODEGAL, FECHA_RECEPCION_BODEGAL FROM
ERP.ORDER_HEADER WHERE ((STATUS_ID = :v0 OR STATUS_ID = :v1 OR STATUS_ID = :v2) AND
(ORDER_TYPE_ID = :v3)) ORDER BY ORDER_DATE DESC
是很慢的。我们测试执行,而不DISTINCT查询,大约需要30秒。还有在表4.000.000+寄存器。 有指数为PK字段订单ID和几乎所有其他字段
与DISTINCT解释计划是:
SELECT STATEMENT () (null)
SORT (ORDER BY) (null)
HASH (UNIQUE) (null)
TABLE ACCESS (FULL) ORDER_HEADER
和无DISTINCT是:
SELECT STATEMENT () (null)
SORT (ORDER BY) (null)
TABLE ACCESS (FULL) ORDER_HEADER
有关调整Oracle任何想法,以改善这种查询的性能? 这是非常困难的重写查询,因为被ofbiz的自动生成 所以我认为该解决方案是关于调整Oracle
由于事先
编辑:我使用TKPROF分析该查询,通过罗布面包车Wijk和haffax的建议,并且结果是以下
********************************************************************************
SELECT DISTINCT ORDER_ID, ORDER_TYPE_ID, ORDER_NAME, EXTERNAL_ID,
SALES_CHANNEL_ENUM_ID, ORDER_DATE, ENTRY_DATE, VISIT_ID, STATUS_ID, CREATED_BY,
FIRST_ATTEMPT_ORDER_ID, CURRENCY_UOM, SYNC_STATUS_ID, BILLING_ACCOUNT_ID,
ORIGIN_FACILITY_ID, WEB_SITE_ID, PRODUCT_STORE_ID, TERMINAL_ID, TRANSACTION_ID,
AUTO_ORDER_SHOPPING_LIST_ID, NEEDS_INVENTORY_ISSUANCE, IS_RUSH_ORDER, INTERNAL_CODE,
REMAINING_SUB_TOTAL, GRAND_TOTAL, LAST_UPDATED_STAMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP,
CREATED_TX_STAMP, RECIBIR_BODEGAL, RECEPCIONADA_BODEGAL, FECHA_RECEPCION_BODEGAL FROM
ERP.ORDER_HEADER WHERE STATUS_ID = 'ORDER_COMPLETED' ORDER BY ORDER_DATE DESC
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.03 0.01 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 1 9.10 160.81 66729 65203 37 50
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 3 9.14 160.83 66729 65203 37 50
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 58
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
db file scattered read 8178 0.28 146.55
direct path write temp 2200 0.04 4.22
direct path read temp 36 0.14 2.01
SQL*Net more data to client 3 0.00 0.00
SQL*Net message from client 1 3.36 3.36
********************************************************************************
如此看来问题是“散读取数据库文件”,任何想法如何优化Oracle为了减少此事件中的等待?
与新TKPROF结果随访,此时关闭会话:
********************************************************************************
SELECT DISTINCT ORDER_ID, ORDER_TYPE_ID, ORDER_NAME, EXTERNAL_ID,
SALES_CHANNEL_ENUM_ID, ORDER_DATE, ENTRY_DATE, VISIT_ID, STATUS_ID, CREATED_BY,
FIRST_ATTEMPT_ORDER_ID, CURRENCY_UOM, SYNC_STATUS_ID, BILLING_ACCOUNT_ID,
ORIGIN_FACILITY_ID, WEB_SITE_ID, PRODUCT_STORE_ID, TERMINAL_ID, TRANSACTION_ID,
AUTO_ORDER_SHOPPING_LIST_ID, NEEDS_INVENTORY_ISSUANCE, IS_RUSH_ORDER, INTERNAL_CODE,
REMAINING_SUB_TOTAL, GRAND_TOTAL, LAST_UPDATED_STAMP, LAST_UPDATED_TX_STAMP, CREATED_STAMP,
CREATED_TX_STAMP, RECIBIR_BODEGAL, RECEPCIONADA_BODEGAL, FECHA_RECEPCION_BODEGAL FROM
ERP.ORDER_HEADER WHERE STATUS_ID = 'ORDER_COMPLETED' ORDER BY ORDER_DATE DESC
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.03 0.01 0 0 0 0
Execute 2 0.00 0.00 0 0 0 0
Fetch 1 8.23 47.66 66576 65203 31 50
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 4 8.26 47.68 66576 65203 31 50
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 58
Rows Row Source Operation
------- ---------------------------------------------------
50 SORT ORDER BY (cr=65203 pr=66576 pw=75025 time=47666679 us)
3456659 TABLE ACCESS FULL ORDER_HEADER (cr=65203 pr=65188 pw=0 time=20757300 us)
Elapsed times include waiting on following events:
Event waited on Times Max. Wait Total Waited
---------------------------------------- Waited ---------- ------------
SQL*Net message to client 1 0.00 0.00
db file scattered read 8179 0.14 34.96
direct path write temp 2230 0.00 3.91
direct path read temp 52 0.14 0.84
SQL*Net more data to client 3 0.00 0.00
SQL*Net message from client 1 1510.62 1510.62
********************************************************************************
解决方案
如果这两个查询之间的差异是显着的,这将是令人惊讶的。你提到,如果没有DISTINCT查询需要大约30秒。多少时间与DISTINCT查询时间?
你能显示查询的TKPROF输出与DISTINCT,你被曝用“改变会话组事件‘10046跟踪名字永远背景下,8级’”,并断开查询已完成后,在会议结束后?这样我们就可以看到时间的实际花费,如果它是在等待什么(“直接路径读取温度”也许?)
此致 罗布。
跟进,所述TKPROF文件发布后:
我看你设法让TKPROF输出,可惜你没有创建TKPROF文件之前断开的会话。现在,光标保持开放,并没有写STAT#线到您的跟踪文件。这就是为什么你没有在你的TKPROF文件中的计划/行源工作。这将是很好,如果你可以重复此过程,若跌破该建议被证明是垃圾。
从我身边一点点炒作:我认为DISTINCT几乎无操作,因为你选择这么多列。如果这是真的,那么你的谓词“WHERE STATUS_ID =‘ORDER_COMPLETED’”是非常有选择性的,你将不必在此列索引中受益。在创建索引之后,请确保你分析得当,甚至与如果数据值是偏斜的直方图。最终的结果将是该查询一个不同的计划,从索引范围扫描,随后是:表存取BY ROWID,导致非常快速的查询。
您已经创建了一个索引之后,可以有表重新分析,包括使用该语句的直方图:
EXEC dbms_stats.gather_table_stats([所有者],[表名],级联=>真,了method_opt = 'FOR ALL索引列SIZE'>)
此致 罗布。
其他提示
既然你订购根据order_date
重要的是,你必须在该字段降序索引结果。
还告诉您要使用该索引Oracle。第一放置order_date
字段在查询和使用像一个提示
SELECT /*+ index(HEADERS IDX_ORDER_DATE_DESC) */ ...
FROM ERP.ORDER_HEADER HEADERS
WHERE ...
ORDER BY ORDER_DATE DESC
这是不是这么多有指标,而是关于告诉Oracle使用它们。甲骨文是关于指数非常挑剔。你得到最佳的效果,当你根据你的最重要的查询选择指标。如有疑问,请跟踪查询。这样,您就可以在查询Oracle的哪一部分看到花费最多时间和你的指数是否真的回升与否。战斗性能问题时跟踪是非常宝贵的。
时ORDER_ID声明为使用PRIMARY KEY约束的PK?因为如果是我期望优化器认识到DISTINCT在此查询多余和优化它。如果没有约束,也不会知道它是多余的,所以会花费在“移除重复”的结果,不必要的和相当大的努力。
尝试禁用散列聚合:
select /*+ no_use_hash_aggregation*/ distinct ...
http://oracle-randolf.blogspot.com/2011/ 01 /散列aggregation.html
当故障排除,我没有SQL我发现DBMS_SQLTUNE封装节省了大量的时间的控制应用。请参见 http://download.oracle.com/docs /cd/B28359_01/appdev.111/b28419/d_sqltun.htm ,是的,不幸的是,你应该许可使用它。
有此包到运行针对在共享池中或AWR储存库中的特定SQL_ID调谐分析程序。分析将包含索引建议,如果有要通过附加的索引进行任何改进。更重要的是,分析可能会发现,它可以与甲骨文调用SQL配置文件实施的改进访问路径 - 这是一组将被保存,无论何时执行该SQL_ID使用的提示。出现这种情况,而不需要在SQL语句中要编码的提示,并有也是一种选择做什么,如果你的应用程序中声明,而不是绑定变量产生文本值,你能想到的模糊匹配的。
当然,这个工具不应该是理解应用程序的替代品,它的数据结构,但通过详细介绍一个更好的计划(如果找到)的执行路径输出读书可以教育。
甲骨文每次运行查询(TABLE ACCESS(FULL))时间访问整个表。 在STATUS_ID和ORDER_TYPE_ID列创建索引
CREATE INDEX ERP.ORDER_HEADER_I1 ON ERP.ORDER_HEADER ( STATUS_ID, ORDER_TYPE_ID );
将有很大的帮助,特别是如果有在ORDER_HEADER表STATUS_ID和ORDER_TYPE_ID的几个不同的值。