今天碰到一SQL, 感觉典型的优化, 好久没有遇到怎么好的案例了, 简单记录之
中午 和朋友们交流SQL, 感觉交流SQL属于比较难的了, 像在OLAP系统中报表里面常用的。突然 以女DBA发来一个SQL, 外话,这个女DBA 大有来头。 OCM级别, 公司
更是牛逼!
SELECT COUNT(*)
FROM (SELECT DISTINCT t1.ID,
t1.ITEM_ID,
t1.ITEM_DESCRIPTION,
t1.CATEGORY_NODE_ID,
t1.CATEGORY_NAME,
t1.CATEGORY_CODE,
t1.MIDCAT_NODE_ID,
t1.MIDCAT_NAME,
t1.MIDCAT_CODE,
t1.SUBCAT_NODE_ID,
t1.SUBCAT_NAME,
t1.SUBCAT_CODE,
t1.COMMODITY_NODE_ID,
t1.COMMODITY_NAME,
t1.COMMODITY_CODE,
t1.TAX_RATE,
t1.PRICE_TYPE,
t1.SUPPLIER_ID,
t1.SUPPLIER_NAME,
t1.MANU_ID,
t1.MANU_NAME,
t1.BUYER_ORG_ID,
t1.SUP_TYPE,
t1.PRICE_TERMS,
t1.CATALOG_TYPE,
PRICE_INFO.BPO_AMT_HEADER_ID,
PRICE_INFO.SOURCE_LINEID,
PRICE_INFO.BATCH_NUMBER,
PRICE_INFO.BPO_LINE_NUM,
PRICE_INFO.NO_TAX_PRICE,
PRICE_INFO.EXIST_TAX_PRICE,
PRICE_INFO.TRANS_EXP,
PRICE_INFO.INCI_EXP,
PRICE_INFO.TARIFFCOST,
PRICE_INFO.INSURANCECOST,
PRICE_INFO.TIERED_QTY,
PRICE_INFO.INPUTORDERID,
PRICE_INFO.OTHER_COST,
PRICE_INFO.PROC_MODE,
PRICE_INFO.SOURCE
FROM PC_CA_PROC_DETAILS t1, PC_CA_PROC_PRICING_DETAILS PRICE_INFO
WHERE (PRICE_INFO.CA_PROC_LINE_ID = t1.ID AND
(PRICE_INFO.RECORD_STATUS = 'ACTIVE') AND
(PRICE_INFO.VALID_FROM <= to_date('20170118 00:00:00','yyyymmdd hh24:mi:ss')) AND
(PRICE_INFO.VALID_TO >= to_date('20170118 23:44:44','yyyymmdd hh24:mi:ss')) AND
((PRICE_INFO.NO_TAX_PRICE > 0) OR(PRICE_INFO.EXIST_TAX_PRICE > 0)))
AND (t1.BUYER_ORG_ID IN ('ORG43', 'ORG00001'))
AND (t1.STATUS = 'ACTIVE')
AND (t1.MANU_NAME = '宝鸡住金石油钢管有限公司')) a
是分页语句中的SQL, 简单看下, 大致知道大概。 执行计划:
-----------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
-----------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 4 | 1496 | 00:00:18 |
| 1 | SORT AGGREGATE | | 1 | 4 | | |
| 2 | VIEW | | 207 | 828 | 1496 | 00:00:18 |
| 3 | HASH UNIQUE | | 207 | 204309 | 1496 | 00:00:18 |
| 4 | NESTED LOOPS | | | | | |
| 5 | NESTED LOOPS | | 207 | 204309 | 1495 | 00:00:18 |
| * 6 | TABLE ACCESS BY INDEX ROWID | PC_CA_PROC_DETAILS | 207 | 161460 | 803 | 00:00:10 |
| * 7 | INDEX RANGE SCAN | IND_PCPD_MANUNAME | 2936 | | 24 | 00:00:01 |
| * 8 | INDEX RANGE SCAN | IDX_PCPPD_RIBC | 1 | | 3 | 00:00:01 |
| * 9 | TABLE ACCESS BY INDEX ROWID | PC_CA_PROC_PRICING_DETAILS | 1 | 207 | 4 | 00:00:01 |
-----------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
------------------------------------------
* 6 - filter("T1"."STATUS"='ACTIVE' AND ("T1"."BUYER_ORG_ID"='ORG00001' OR "T1"."BUYER_ORG_ID"='ORG43'))
* 7 - access("T1"."MANU_NAME"='瀹濋浮浣忛噾鐭虫补閽㈢鏈夐檺鍏徃')
* 8 - access("PRICE_INFO"."CA_PROC_LINE_ID"="T1"."ID" AND "PRICE_INFO"."RECORD_STATUS"='ACTIVE')
* 9 - filter("PRICE_INFO"."VALID_TO">=TO_DATE(' 2017-01-18 23:44:44', 'syyyy-mm-dd hh24:mi:ss') AND "PRICE_INFO"."VALID_FROM"<=TO_DATE(' 2017-01-18 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND
("PRICE_INFO"."NO_TAX_PRICE">0 OR "PRICE_INFO"."EXIST_TAX_PRICE">0))
问她这个可以尝试 下走hash, 她说走hash 后结果出不了, 很慢很慢了, 她看了等待事件 ,
不亏是OCM, 很快知道这个是bug, 没办法 这个等待事件, 哥不懂, 于是继续优化,
开始看到SQL,以为hash 的, 后来看到数据量, 决定改为半连接, 哎 本来一眼就可以看出SQL怎么优化的, 不过还好殊途同归。 最后的 执行计划
最终原来SQL 40多S, 后来改后 0.5S ,
至此,优化结束。