再一次利用with as 优化SQL
上海的一个哥们问我有个SQL跑了4个小时都没跑完,实在受不了了,找我优化一下。我确实挺佩服他的,要是我遇到跑了几分钟的,就受不了了。
SQL语句和执行计划如下:
--sql id:1qbbw3th4x8yc
SELECT "VOUCHER".FID "ID",
"ENTRIES".FID "ENTRIES.ID",
"ENTRIES".FEntryDC "ENTRIES.ENTRYDC",
"ACCOUNT".FID "ACCOUNT.ID",
"ENTRIES".FCurrencyID "CURRENCY.ID",
"PERIOD".FNumber "PERIOD.NUMBER",
"ENTRIES".FSeq "ENTRIES.SEQ",
"ENTRIES".FLocalExchangeRate "LOCALEXCHANGERATE",
"ENTRIES".FReportingExchangeRate "REPORTINGEXCHANGERATE",
"ENTRIES".FMeasureUnitID "ENTRYMEASUREUNIT.ID",
"ASSISTRECORDS".FID "ASSISTRECORDS.ID",
"ASSISTRECORDS".FSeq "ASSISTRECORDS.SEQ",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FOriginalAmount
ELSE
"ASSISTRECORDS".FOriginalAmount
END "ASSISTRECORDS.ORIGINALAMOUNT",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FLocalAmount
ELSE
"ASSISTRECORDS".FLocalAmount
END "ASSISTRECORDS.LOCALAMOUNT",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FReportingAmount
ELSE
"ASSISTRECORDS".FReportingAmount
END "ASSISTRECORDS.REPORTINGAMOUNT",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FQuantity
ELSE
"ASSISTRECORDS".FQuantity
END "ASSISTRECORDS.QUANTITY",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FStandardQuantity
ELSE
"ASSISTRECORDS".FStandardQuantity
END "ASSISTRECORDS.STANDARDQTY",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FPrice
ELSE
"ASSISTRECORDS".FPrice
END "ASSISTRECORDS.PRICE",
CASE
WHEN ("ACCOUNT".FCAA IS NULL) THEN
NULL
ELSE
"ASSISTRECORDS".FAssGrpID
END "ASSGRP.ID"
FROM T_GL_Voucher "VOUCHER"
LEFT OUTER JOIN T_BD_Period "PERIOD"
ON "VOUCHER".FPeriodID = "PERIOD".FID
INNER JOIN T_GL_VoucherEntry "ENTRIES"
ON "VOUCHER".FID = "ENTRIES".FBillID
INNER JOIN T_BD_AccountView "ACCOUNT"
ON "ENTRIES".FAccountID = "ACCOUNT".FID
LEFT OUTER JOIN T_GL_VoucherAssistRecord "ASSISTRECORDS"
ON "ENTRIES".FID = "ASSISTRECORDS".FEntryID
WHERE "VOUCHER".FID IN
(SELECT "VOUCHER".FID "ID"
FROM T_GL_Voucher "VOUCHER"
INNER JOIN T_GL_VoucherEntry "ENTRIES"
ON "VOUCHER".FID = "ENTRIES".FBillID
INNER JOIN T_BD_AccountView "ACCOUNT"
ON "ENTRIES".FAccountID = "ACCOUNT".FID
INNER JOIN t_bd_accountview PAV
ON ((INSTR("ACCOUNT".flongnumber, pav.flongnumber) = 1 AND
pav.faccounttableid = "ACCOUNT".faccounttableid) AND
pav.fcompanyid = "ACCOUNT".fcompanyid)
WHERE (("VOUCHER".FCompanyID IN ('fSSF82rRSKexM3KKN1d0tMznrtQ=')) AND
(("VOUCHER".FBizStatus IN (5)) AND
((("VOUCHER".FPeriodID IN ('+wQxkBFVRiKnV7OniceMDoI4jEw=')) AND
"ENTRIES".FCurrencyID =
'dfd38d11-00fd-1000-e000-1ebdc0a8100dDEB58FDC') AND
(pav.FID IN ('vyPiKexLRXiyMb41VSVVzJ2pmCY='))))))
ORDER BY "ID" ASC, "ENTRIES.SEQ" ASC, "ASSISTRECORDS.SEQ" ASC
--执行计划
--------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
--------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 13 | 5733 | 486 (1)|
| 1 | SORT ORDER BY | | 13 | 5733 | 486 (1)|
| 2 | VIEW | VM_NWVW_2 | 13 | 5733 | 486 (1)|
| 3 | HASH UNIQUE | | 13 | 11115 | 486 (1)|
| 4 | NESTED LOOPS OUTER | | 13 | 11115 | 485 (1)|
| 5 | NESTED LOOPS | | 9 | 6606 | 471 (1)|
| 6 | NESTED LOOPS | | 9 | 6057 | 467 (1)|
| 7 | MERGE JOIN OUTER | | 1 | 473 | 459 (1)|
| 8 | HASH JOIN | | 1 | 427 | 458 (1)|
| 9 | NESTED LOOPS | | | | |
| 10 | NESTED LOOPS | | 258 | 83850 | 390 (0)|
| 11 | NESTED LOOPS | | 6 | 1332 | 3 (0)|
| 12 | TABLE ACCESS BY INDEX ROWID| T_BD_ACCOUNTVIEW | 1 | 111 | 2 (0)|
| 13 | INDEX UNIQUE SCAN | PK_BD_ACCOUNTVIEW | 1 | | 1 (0)|
| 14 | INDEX RANGE SCAN | IX_BD_ACTCOMLNUM | 6 | 666 | 1 (0)|
| 15 | INDEX RANGE SCAN | IX_GL_VCHAACCT | 489 | | 1 (0)|
| 16 | TABLE ACCESS BY INDEX ROWID | T_GL_VOUCHERENTRY | 42 | 4326 | 65 (0)|
| 17 | INDEX RANGE SCAN | IX_GL_VCH_11 | 7536 | 750K| 68 (0)|
| 18 | BUFFER SORT | | 1 | 46 | 391 (0)|
| 19 | INDEX RANGE SCAN | IX_PERIOD_ENC | 1 | 46 | 1 (0)|
| 20 | TABLE ACCESS BY INDEX ROWID | T_GL_VOUCHERENTRY | 17 | 3400 | 8 (0)|
| 21 | INDEX RANGE SCAN | IX_GL_VCHENTRYFQ1 | 17 | | 1 (0)|
| 22 | TABLE ACCESS BY INDEX ROWID | T_BD_ACCOUNTVIEW | 1 | 61 | 1 (0)|
| 23 | INDEX UNIQUE SCAN | PK_BD_ACCOUNTVIEW | 1 | | 1 (0)|
| 24 | TABLE ACCESS BY INDEX ROWID | T_GL_VOUCHERASSISTRECORD | 1 | 121 | 2 (0)|
| 25 | INDEX RANGE SCAN | IX_GL_VCHASSREC_11 | 2 | | 1 (0)|
--------------------------------------------------------------------------------------------------------
Note
-----
- 'PLAN_TABLE' is old version
我靠 plan_table is old version....一般遇到这种执行计划发给我 我是理都不理的,但是 这哥们关系好,算了吧 勉为其难。
那我就不从执行计划 入手优化了,直接分析sql语句优化。这个sql挺简单的,from 后面几个表, where 有个 in ,最后有个order by
问他 in 后面返回多少记录
落落 17:11:46
哦
你先看 where in 里面跑多久
上海-咖啡迷 17:12:40
很快
23s 16880rows
其他表大小如下
看到这些就知道怎么优化了 。之前跑4个小时不出结果,那行嘛 我给你优化到1分钟
in 只返回16880条数据,那么可以用in作为驱动表去驱动 T_GL_Voucher
思路 就跟 这个博客一样的 http://blog.csdn.net/robinson1988/article/details/10551467 我靠 居然还个sb在乱评论
因为in里面有点复杂,不好用hint,我偷懒,难得去搞了,直接 用下面的sql 优化
with x as (SELECT /*+ materialize */ "VOUCHER".FID "ID"
FROM T_GL_Voucher "VOUCHER"
INNER JOIN T_GL_VoucherEntry "ENTRIES"
ON "VOUCHER".FID = "ENTRIES".FBillID
INNER JOIN T_BD_AccountView "ACCOUNT"
ON "ENTRIES".FAccountID = "ACCOUNT".FID
INNER JOIN t_bd_accountview PAV
ON ((INSTR("ACCOUNT".flongnumber, pav.flongnumber) = 1 AND
pav.faccounttableid = "ACCOUNT".faccounttableid) AND
pav.fcompanyid = "ACCOUNT".fcompanyid)
WHERE (("VOUCHER".FCompanyID IN ('fSSF82rRSKexM3KKN1d0tMznrtQ=')) AND
(("VOUCHER".FBizStatus IN (5)) AND
((("VOUCHER".FPeriodID IN ('+wQxkBFVRiKnV7OniceMDoI4jEw=')) AND
"ENTRIES".FCurrencyID =
'dfd38d11-00fd-1000-e000-1ebdc0a8100dDEB58FDC') AND
(pav.FID IN ('vyPiKexLRXiyMb41VSVVzJ2pmCY='))))))
SELECT "VOUCHER".FID "ID",
"ENTRIES".FID "ENTRIES.ID",
"ENTRIES".FEntryDC "ENTRIES.ENTRYDC",
"ACCOUNT".FID "ACCOUNT.ID",
"ENTRIES".FCurrencyID "CURRENCY.ID",
"PERIOD".FNumber "PERIOD.NUMBER",
"ENTRIES".FSeq "ENTRIES.SEQ",
"ENTRIES".FLocalExchangeRate "LOCALEXCHANGERATE",
"ENTRIES".FReportingExchangeRate "REPORTINGEXCHANGERATE",
"ENTRIES".FMeasureUnitID "ENTRYMEASUREUNIT.ID",
"ASSISTRECORDS".FID "ASSISTRECORDS.ID",
"ASSISTRECORDS".FSeq "ASSISTRECORDS.SEQ",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FOriginalAmount
ELSE
"ASSISTRECORDS".FOriginalAmount
END "ASSISTRECORDS.ORIGINALAMOUNT",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FLocalAmount
ELSE
"ASSISTRECORDS".FLocalAmount
END "ASSISTRECORDS.LOCALAMOUNT",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FReportingAmount
ELSE
"ASSISTRECORDS".FReportingAmount
END "ASSISTRECORDS.REPORTINGAMOUNT",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FQuantity
ELSE
"ASSISTRECORDS".FQuantity
END "ASSISTRECORDS.QUANTITY",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FStandardQuantity
ELSE
"ASSISTRECORDS".FStandardQuantity
END "ASSISTRECORDS.STANDARDQTY",
CASE
WHEN (("ACCOUNT".FCAA IS NULL) AND
("ACCOUNT".FhasUserProperty <> 1)) THEN
"ENTRIES".FPrice
ELSE
"ASSISTRECORDS".FPrice
END "ASSISTRECORDS.PRICE",
CASE
WHEN ("ACCOUNT".FCAA IS NULL) THEN
NULL
ELSE
"ASSISTRECORDS".FAssGrpID
END "ASSGRP.ID"
FROM T_GL_Voucher "VOUCHER"
LEFT OUTER JOIN T_BD_Period "PERIOD"
ON "VOUCHER".FPeriodID = "PERIOD".FID
INNER JOIN T_GL_VoucherEntry "ENTRIES"
ON "VOUCHER".FID = "ENTRIES".FBillID
INNER JOIN T_BD_AccountView "ACCOUNT"
ON "ENTRIES".FAccountID = "ACCOUNT".FID
LEFT OUTER JOIN T_GL_VoucherAssistRecord "ASSISTRECORDS"
ON "ENTRIES".FID = "ASSISTRECORDS".FEntryID
WHERE "VOUCHER".FID IN
(select id from x)
ORDER BY "ID" ASC, "ENTRIES.SEQ" ASC, "ASSISTRECORDS.SEQ" ASC
---======执行计划
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)|
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 24 | 11208 | 506 (1)|
| 1 | TEMP TABLE TRANSFORMATION | | | | |
| 2 | LOAD AS SELECT | SYS_TEMP_0FD9D6853_1AD5C99D | | | |
| 3 | HASH JOIN | | 1 | 415 | 458 (1)|
| 4 | NESTED LOOPS | | | | |
| 5 | NESTED LOOPS | | 258 | 83850 | 390 (0)|
| 6 | NESTED LOOPS | | 6 | 1332 | 3 (0)|
| 7 | TABLE ACCESS BY INDEX ROWID| T_BD_ACCOUNTVIEW | 1 | 111 | 2 (0)|
| 8 | INDEX UNIQUE SCAN | PK_BD_ACCOUNTVIEW | 1 | | 1 (0)|
| 9 | INDEX RANGE SCAN | IX_BD_ACTCOMLNUM | 6 | 666 | 1 (0)|
| 10 | INDEX RANGE SCAN | IX_GL_VCHAACCT | 489 | | 1 (0)|
| 11 | TABLE ACCESS BY INDEX ROWID | T_GL_VOUCHERENTRY | 42 | 4326 | 65 (0)|
| 12 | INDEX RANGE SCAN | IX_GL_VCH_11 | 7536 | 662K| 68 (0)|
| 13 | SORT ORDER BY | | 24 | 11208 | 48 (5)|
| 14 | NESTED LOOPS OUTER | | 24 | 11208 | 47 (3)|
| 15 | NESTED LOOPS | | 17 | 6086 | 21 (5)|
| 16 | NESTED LOOPS | | 17 | 5253 | 13 (8)|
| 17 | NESTED LOOPS OUTER | | 1 | 121 | 5 (20)|
| 18 | NESTED LOOPS | | 1 | 87 | 4 (25)|
| 19 | VIEW | VW_NSO_1 | 1 | 29 | 2 (0)|
| 20 | HASH UNIQUE | | 1 | 24 | |
| 21 | VIEW | | 1 | 24 | 2 (0)|
| 22 | TABLE ACCESS FULL | SYS_TEMP_0FD9D6853_1AD5C99D | 1 | 29 | 2 (0)|
| 23 | INDEX RANGE SCAN | IX_GL_VCH_FIDCMPNUM | 1 | 58 | 1 (0)|
| 24 | INDEX RANGE SCAN | IX_PERIOD_ENC | 1 | 34 | 1 (0)|
| 25 | TABLE ACCESS BY INDEX ROWID | T_GL_VOUCHERENTRY | 17 | 3196 | 8 (0)|
| 26 | INDEX RANGE SCAN | IX_GL_VCHENTRYFQ1 | 17 | | 1 (0)|
| 27 | TABLE ACCESS BY INDEX ROWID | T_BD_ACCOUNTVIEW | 1 | 49 | 1 (0)|
| 28 | INDEX UNIQUE SCAN | PK_BD_ACCOUNTVIEW | 1 | | 1 (0)|
| 29 | TABLE ACCESS BY INDEX ROWID | T_GL_VOUCHERASSISTRECORD | 1 | 109 | 2 (0)|
| 30 | INDEX RANGE SCAN | IX_GL_VCHASSREC_11 | 2 | | 1 (0)|
------------------------------------------------------------------------------------------------------
最后 1分钟全部查询出来,42956条数据
其实这个sql 没有 优化彻底,如果真的要认真对待,大概30秒左右就能跑完 不过难得搞了
有sql 要优化 加我qq 692162374 或者 加 群 220761024
想要跟我学优化的,请点击这里
最后我才知道 这个哥们 18k了 现在 我操。。。。他跟我学了ORACLE sql优化大概4个月了
再一次利用with as 优化SQL的更多相关文章
- 【转】利用 force index优化sql语句性能
今天写了一个统计sql,在一个近亿条数据的表上执行,200s都查不出结果.SQL如下: select customer,count(1) c from upv_** where created bet ...
- 利用 force index优化sql语句性能
[转自:https://blog.csdn.net/bruce128/article/details/46777567]并进行总结 今天写了一个统计sql,在一个近亿条数据的表上执行,200s都查不出 ...
- 利用查询提示优化SQL
数据库环境:SQL SERVER 2005 我们来看一下SQL语句及对应的数据量 SELECT COUNT(*) FROM cinvout_02 a WHERE ( a.dept_id IN ( SE ...
- 利用ordered hints优化SQL
SQL_ID 4g70n3k9bqc5v, child number 0 ------------------------------------- MERGE INTO YJBZH_GRXDFHZ ...
- 利用DBMS_SQLTUNE优化SQL
DBMS_SQLTUNE优化SQL是在oracle10g才出来的新特性,使用它能很大程度上方便对sql的分析和优化.执行DBMS_SQLTUNE包进行sql优化需要有advisor的权限: stat& ...
- 【转】使用SQL Tuning Advisor STA优化SQL
SQL优化器(SQL Tuning Advisor STA)是Oracle10g中推出的帮助DBA优化工具,它的特点是简单.智能,DBA值需要调用函数就可以给出一个性能很差的语句的优化结果.下面介绍一 ...
- sql语句优化SQL Server
MS SQL Server查询优化方法查询速度慢的原因很多,常见如下几种 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了 ...
- mysql优化SQL语句的一般步骤及常用方法
一.优化SQL语句的一般步骤 1. 通过show status命令了解各种SQL的执行频率 mysqladmin extended-status 或: show [session|global]sta ...
- 转载 50种方法优化SQL Server数据库查询
原文地址 http://www.cnblogs.com/zhycyq/articles/2636748.html 50种方法优化SQL Server数据库查询 查询速度慢的原因很多,常见如下几种: 1 ...
随机推荐
- 关于Python缩进,我们该了解哪些?
Python是一门独特的语言,它的代码块是通过缩进(Indentation)来标记的(大部分语言都是使用花括号作为代码块的标记),具有相同缩进的多行代码属于同一个代码块.如果代码莫名其妙的乱缩进,Py ...
- BootstrapValidator实现注册校验和登录错误提示效果(转)
使用BootstrapValidator进行注册校验和登录错误提示,具体内容如下 1.介绍 在AdminEAP框架中,使用了BootstrapValidator校验框架,本文以注册校验的用户名.登录名 ...
- sqlserver 取月初月末的时间
1.取月初的时间 --getdate() :2012/05/08 19:29:00 select convert(varchar,dateadd(day,-day(getdate())+1,ge ...
- Leetcode876.Middle of the Linked List链表的中间节点
给定一个带有头结点 head 的非空单链表,返回链表的中间结点. 如果有两个中间结点,则返回第二个中间结点. 示例 1: 输入:[1,2,3,4,5] 输出:此列表中的结点 3 (序列化形式:[3,4 ...
- 如何建一个Liferay 7的theme
首先附上原文链接Creating theme and Deploying in liferay 7 by using Eclipse 1.第一步:建一个Liferay module 项目,选择them ...
- startActivity 流程图
- 【JZOJ4803】【NOIP2016提高A组模拟9.28】求导
题目描述 输入 输出 样例输入 2x^2+3x+1 样例输出 4x+3 数据范围 样例解释 求导的意思: 多项式是由若干个单项式构成的 单项式的一般形式是ax^b,其中ab都是常数,x是自变量 对于单 ...
- CF789D Mike and distribution
题目连接 一道人类智慧题.... 这道题目可以转化为在a,b中的选出一些位置,使得这些位置处的值加起来大于没有选的位置的值 我们按照a的权值排序,选择第一个元素,其与元素两两分组,每组选择b更大的那一 ...
- Android实战:手把手实现“捧腹网”APP(一)-----捧腹网网页分析、数据获取
Android实战:手把手实现"捧腹网"APP(一)-–捧腹网网页分析.数据获取 Android实战:手把手实现"捧腹网"APP(二)-–捧腹APP原型设计.实 ...
- hdu2018 dp
/* 1~4直接取得: 然后后面的生牛的时候都是前一年的加上一定的数. 从第5年看,第五年出生的牛肯定要加上第四年出生的,然后由于第一个出生的牛开始生小牛,这和 最开始的牛生孩子是一样的,所以+dp[ ...