Oracle Database 11g 11.2.0.4.0版 - 64位生产
解决:是由基数反馈引起的。我以为我之前已经对它进行了测试并将其消除了,但显然是错了。
将此添加到查询中:
select --+ opt_param('_optimizer_use_feedback' 'false')
现在一直很快。
我有这种奇怪的情况,在前两次执行中查询似乎运行得相当快,然后在后续执行时慢得多。我正在使用sqlplus和#34;设置autotrace on"获取查询计划,并且对于每次运行,计划是相同的(相同的行估计等)。最后的autotrace统计信息表明在后续执行中会读取更多数据。
如果我在语法上更改查询(只需添加或删除注释),那么它可能是SQL缓存的新内容,然后它会快速运行两次,然后再慢慢运行。如果我将其更改回我之前使用的查询版本(因此在缓存中),那么它总是很慢。
我认为它与cardinality feedback无关,因为:
那我下一步该看哪儿?我可以用什么工具来缩小发生这种情况的原因?
这是我正在测试的查询:
set timing on
set autotrace on
select distinct
cc2.circuit_id as circuit_id
, cc2.circuit_component_id as component_circuit_id
from bsdb.bs_instance si
join bsdb.bs_location_schedule ls
on ls.bs_instance_id = si.id
and coalesce(ls.terminated_date, sysdate) >= sysdate
join npc.npc_customer_service cs
on cs.bs_location_schedule_id = ls.id
and cs.circuit_status_id in (1, 2, 6)
join tdb.loc_site_code lsc
on lsc.id = ls.site_code_id
left outer join scdb.brand br
on br.id = si.brand_id
join tdb.organisation o
on o.org_code = coalesce(br.brand_org_code, si.client_org_code)
and o.org_code = 2421
join npc.npc_customer_service_circuit csc
on csc.customer_service_id = cs.customer_service_id
and coalesce(csc.end_date, sysdate) >= sysdate
join npc.npc_circuit_component cc
on cc.circuit_id = csc.circuit_id
and coalesce(cc.end_date, sysdate) >= sysdate
join npc.npc_circuit_hierarchy ch
on ch.sub_circuit_id = cc.circuit_component_id
join npc.npc_circuit_component cc2
on cc2.circuit_id = ch.master_circuit_id
and coalesce(cc2.end_date, sysdate) >= sysdate
;
如果我将外连接移除到scdb.brand(在这种特定情况下不是必需的,但通常用于此查询),那么在多次运行中性能快速且一致。
autotrace输出包括计划,快速运行:
109 rows selected.
Elapsed: 00:00:00.51
Execution Plan
Plan hash value: 2956052167
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 173 | 18857 | 2069 (6)| 00:00:07 |
| 1 | HASH UNIQUE | | 173 | 18857 | 2069 (6)| 00:00:07 |
|* 2 | FILTER | | | | | |
|* 3 | HASH JOIN OUTER | | 173 | 18857 | 2068 (6)| 00:00:07 |
|* 4 | HASH JOIN | | 173 | 17473 | 2063 (6)| 00:00:07 |
|* 5 | HASH JOIN | | 173 | 15397 | 2000 (6)| 00:00:07 |
| 6 | NESTED LOOPS | | 244 | 18056 | 1297 (2)| 00:00:05 |
| 7 | NESTED LOOPS | | 249 | 18056 | 1297 (2)| 00:00:05 |
| 8 | NESTED LOOPS | | 249 | 15438 | 799 (3)| 00:00:03 |
|* 9 | HASH JOIN | | 205 | 9635 | 183 (9)| 00:00:01 |
|* 10 | HASH JOIN | | 280 | 8960 | 110 (5)| 00:00:01 |
|* 11 | TABLE ACCESS FULL | BS_LOCATION_SCHEDULE | 695 | 12510 | 44 (7)| 00:00:01 |
| 12 | NESTED LOOPS | | 3452 | 48328 | 66 (4)| 00:00:01 |
|* 13 | INDEX UNIQUE SCAN | ORGANISATION__PK | 1 | 4 | 1 (0)| 00:00:01 |
|* 14 | TABLE ACCESS FULL | NPC_CUSTOMER_SERVICE | 3452 | 34520 | 65 (4)| 00:00:01 |
|* 15 | TABLE ACCESS FULL | NPC_CUSTOMER_SERVICE_CIRCUIT | 2531 | 37965 | 72 (13)| 00:00:01 |
|* 16 | TABLE ACCESS BY INDEX ROWID| NPC_CIRCUIT_COMPONENT | 1 | 15 | 3 (0)| 00:00:01 |
|* 17 | INDEX RANGE SCAN | NPC_CIRCUIT_COMPONENT_I01 | 9 | | 2 (0)| 00:00:01 |
|* 18 | INDEX UNIQUE SCAN | NPC_CIRCUIT_HIERARCHY_I02 | 1 | | 1 (0)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | NPC_CIRCUIT_HIERARCHY | 1 | 12 | 2 (0)| 00:00:01 |
|* 20 | TABLE ACCESS FULL | NPC_CIRCUIT_COMPONENT | 23529 | 344K| 702 (13)| 00:00:03 |
| 21 | TABLE ACCESS FULL | BS_INSTANCE | 13483 | 158K| 63 (2)| 00:00:01 |
| 22 | TABLE ACCESS FULL | BRAND | 1246 | 9968 | 5 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(COALESCE("BR"."BRAND_ORG_CODE","SI"."CLIENT_ORG_CODE")=2421)
3 - access("BR"."ID"(+)="SI"."BRAND_ID")
4 - access("LS"."BS_INSTANCE_ID"="SI"."ID")
5 - access("CC2"."CIRCUIT_ID"="CH"."MASTER_CIRCUIT_ID")
9 - access("CSC"."CUSTOMER_SERVICE_ID"="CS"."CUSTOMER_SERVICE_ID")
10 - access("CS"."BS_LOCATION_SCHEDULE_ID"="LS"."ID")
11 - filter(COALESCE("LS"."TERMINATED_DATE",SYSDATE@!)>=SYSDATE@! AND "LS"."SITE_CODE_ID" IS NOT NULL)
13 - access("O"."ORG_CODE"=2421)
14 - filter("CS"."BS_LOCATION_SCHEDULE_ID" IS NOT NULL AND ("CS"."CIRCUIT_STATUS_ID"=1 OR
"CS"."CIRCUIT_STATUS_ID"=2 OR "CS"."CIRCUIT_STATUS_ID"=6))
15 - filter(COALESCE("CSC"."END_DATE",SYSDATE@!)>=SYSDATE@!)
16 - filter(COALESCE("CC"."END_DATE",SYSDATE@!)>=SYSDATE@!)
17 - access("CC"."CIRCUIT_ID"="CSC"."CIRCUIT_ID")
18 - access("CH"."SUB_CIRCUIT_ID"="CC"."CIRCUIT_COMPONENT_ID")
20 - filter(COALESCE("CC2"."END_DATE",SYSDATE@!)>=SYSDATE@!)
Statistics
29 recursive calls
0 db block gets
45368 consistent gets
0 physical reads
0 redo size
3423 bytes sent via SQL*Net to client
576 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
109 rows processed
autotrace输出包括计划,慢跑:
109 rows selected.
Elapsed: 00:00:02.67
Execution Plan
Plan hash value: 2956052167
--------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 173 | 18857 | 2069 (6)| 00:00:07 |
| 1 | HASH UNIQUE | | 173 | 18857 | 2069 (6)| 00:00:07 |
|* 2 | FILTER | | | | | |
|* 3 | HASH JOIN OUTER | | 173 | 18857 | 2068 (6)| 00:00:07 |
|* 4 | HASH JOIN | | 173 | 17473 | 2063 (6)| 00:00:07 |
|* 5 | HASH JOIN | | 173 | 15397 | 2000 (6)| 00:00:07 |
| 6 | NESTED LOOPS | | 244 | 18056 | 1297 (2)| 00:00:05 |
| 7 | NESTED LOOPS | | 249 | 18056 | 1297 (2)| 00:00:05 |
| 8 | NESTED LOOPS | | 249 | 15438 | 799 (3)| 00:00:03 |
|* 9 | HASH JOIN | | 205 | 9635 | 183 (9)| 00:00:01 |
|* 10 | HASH JOIN | | 280 | 8960 | 110 (5)| 00:00:01 |
|* 11 | TABLE ACCESS FULL | BS_LOCATION_SCHEDULE | 695 | 12510 | 44 (7)| 00:00:01 |
| 12 | NESTED LOOPS | | 3452 | 48328 | 66 (4)| 00:00:01 |
|* 13 | INDEX UNIQUE SCAN | ORGANISATION__PK | 1 | 4 | 1 (0)| 00:00:01 |
|* 14 | TABLE ACCESS FULL | NPC_CUSTOMER_SERVICE | 3452 | 34520 | 65 (4)| 00:00:01 |
|* 15 | TABLE ACCESS FULL | NPC_CUSTOMER_SERVICE_CIRCUIT | 2531 | 37965 | 72 (13)| 00:00:01 |
|* 16 | TABLE ACCESS BY INDEX ROWID| NPC_CIRCUIT_COMPONENT | 1 | 15 | 3 (0)| 00:00:01 |
|* 17 | INDEX RANGE SCAN | NPC_CIRCUIT_COMPONENT_I01 | 9 | | 2 (0)| 00:00:01 |
|* 18 | INDEX UNIQUE SCAN | NPC_CIRCUIT_HIERARCHY_I02 | 1 | | 1 (0)| 00:00:01 |
| 19 | TABLE ACCESS BY INDEX ROWID | NPC_CIRCUIT_HIERARCHY | 1 | 12 | 2 (0)| 00:00:01 |
|* 20 | TABLE ACCESS FULL | NPC_CIRCUIT_COMPONENT | 23529 | 344K| 702 (13)| 00:00:03 |
| 21 | TABLE ACCESS FULL | BS_INSTANCE | 13483 | 158K| 63 (2)| 00:00:01 |
| 22 | TABLE ACCESS FULL | BRAND | 1246 | 9968 | 5 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - filter(COALESCE("BR"."BRAND_ORG_CODE","SI"."CLIENT_ORG_CODE")=2421)
3 - access("BR"."ID"(+)="SI"."BRAND_ID")
4 - access("LS"."BS_INSTANCE_ID"="SI"."ID")
5 - access("CC2"."CIRCUIT_ID"="CH"."MASTER_CIRCUIT_ID")
9 - access("CSC"."CUSTOMER_SERVICE_ID"="CS"."CUSTOMER_SERVICE_ID")
10 - access("CS"."BS_LOCATION_SCHEDULE_ID"="LS"."ID")
11 - filter(COALESCE("LS"."TERMINATED_DATE",SYSDATE@!)>=SYSDATE@! AND "LS"."SITE_CODE_ID" IS NOT NULL)
13 - access("O"."ORG_CODE"=2421)
14 - filter("CS"."BS_LOCATION_SCHEDULE_ID" IS NOT NULL AND ("CS"."CIRCUIT_STATUS_ID"=1 OR
"CS"."CIRCUIT_STATUS_ID"=2 OR "CS"."CIRCUIT_STATUS_ID"=6))
15 - filter(COALESCE("CSC"."END_DATE",SYSDATE@!)>=SYSDATE@!)
16 - filter(COALESCE("CC"."END_DATE",SYSDATE@!)>=SYSDATE@!)
17 - access("CC"."CIRCUIT_ID"="CSC"."CIRCUIT_ID")
18 - access("CH"."SUB_CIRCUIT_ID"="CC"."CIRCUIT_COMPONENT_ID")
20 - filter(COALESCE("CC2"."END_DATE",SYSDATE@!)>=SYSDATE@!)
Statistics
0 recursive calls
0 db block gets
82317 consistent gets
0 physical reads
0 redo size
3423 bytes sent via SQL*Net to client
577 bytes received via SQL*Net from client
9 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
109 rows processed
tkprof输出,快速运行:
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.05 0.05 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 9 0.59 0.59 0 65896 0 109
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 11 0.64 0.64 0 65896 0 109
Misses in library cache during parse: 1
Optimizer mode: ALL_ROWS
Parsing user id: 631
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
109 109 109 HASH UNIQUE (cr=65896 pr=0 pw=0 time=596536 us cost=2069 size=18857 card=173)
192 192 192 FILTER (cr=65896 pr=0 pw=0 time=629952 us)
25244 25244 25244 HASH JOIN OUTER (cr=65896 pr=0 pw=0 time=595042 us cost=2068 size=18857 card=173)
25244 25244 25244 HASH JOIN (cr=65874 pr=0 pw=0 time=579863 us cost=2063 size=17473 card=173)
25244 25244 25244 HASH JOIN (cr=65501 pr=0 pw=0 time=408409 us cost=2000 size=15397 card=173)
12247 12247 12247 NESTED LOOPS (cr=61723 pr=0 pw=0 time=338753 us cost=1297 size=18056 card=244)
12247 12247 12247 NESTED LOOPS (cr=49476 pr=0 pw=0 time=276466 us cost=1297 size=18056 card=249)
16700 16700 16700 NESTED LOOPS (cr=24758 pr=0 pw=0 time=232395 us cost=799 size=15438 card=249)
12630 12630 12630 HASH JOIN (cr=995 pr=0 pw=0 time=59090 us cost=183 size=9635 card=205)
5558 5558 5558 HASH JOIN (cr=622 pr=0 pw=0 time=36847 us cost=110 size=8960 card=280)
8984 8984 8984 TABLE ACCESS FULL BS_LOCATION_SCHEDULE (cr=247 pr=0 pw=0 time=6835 us cost=44 size=12510 card=695)
5653 5653 5653 NESTED LOOPS (cr=375 pr=0 pw=0 time=7076 us cost=66 size=48328 card=3452)
1 1 1 INDEX UNIQUE SCAN ORGANISATION__PK (cr=2 pr=0 pw=0 time=38 us cost=1 size=4 card=1)(object id 98786)
5653 5653 5653 TABLE ACCESS FULL NPC_CUSTOMER_SERVICE (cr=373 pr=0 pw=0 time=5278 us cost=65 size=34520 card=3452)
32022 32022 32022 TABLE ACCESS FULL NPC_CUSTOMER_SERVICE_CIRCUIT (cr=373 pr=0 pw=0 time=25562 us cost=72 size=37965 card=2531)
16700 16700 16700 TABLE ACCESS BY INDEX ROWID NPC_CIRCUIT_COMPONENT (cr=23763 pr=0 pw=0 time=131644 us cost=3 size=15 card=1)
17448 17448 17448 INDEX RANGE SCAN NPC_CIRCUIT_COMPONENT_I01 (cr=17401 pr=0 pw=0 time=61607 us cost=2 size=0 card=9)(object id 4306712)
12247 12247 12247 INDEX UNIQUE SCAN NPC_CIRCUIT_HIERARCHY_I02 (cr=24718 pr=0 pw=0 time=78582 us cost=1 size=0 card=1)(object id 4306727)
12247 12247 12247 TABLE ACCESS BY INDEX ROWID NPC_CIRCUIT_HIERARCHY (cr=12247 pr=0 pw=0 time=51413 us cost=2 size=12 card=1)
324238 324238 324238 TABLE ACCESS FULL NPC_CIRCUIT_COMPONENT (cr=3778 pr=0 pw=0 time=161012 us cost=702 size=352935 card=23529)
13529 13529 13529 TABLE ACCESS FULL BS_INSTANCE (cr=373 pr=0 pw=0 time=5917 us cost=63 size=161796 card=13483)
1271 1271 1271 TABLE ACCESS FULL BRAND (cr=22 pr=0 pw=0 time=542 us cost=5 size=9968 card=1246)
********************************************************************************
tkprof输出,慢速运行:
call count cpu elapsed disk query current rows
------- ------ -------- ---------- ---------- ---------- ---------- ----------
Parse 1 0.00 0.00 0 0 0 0
Execute 1 0.00 0.00 0 0 0 0
Fetch 9 5.66 5.66 0 82317 0 109
------- ------ -------- ---------- ---------- ---------- ---------- ----------
total 11 5.66 5.66 0 82317 0 109
Misses in library cache during parse: 0
Optimizer mode: ALL_ROWS
Parsing user id: 631
Number of plan statistics captured: 1
Rows (1st) Rows (avg) Rows (max) Row Source Operation
---------- ---------- ---------- ---------------------------------------------------
109 109 109 HASH UNIQUE (cr=82317 pr=0 pw=0 time=5667122 us cost=16766 size=16723107 card=153423)
192 192 192 FILTER (cr=82317 pr=0 pw=0 time=5865780 us)
25244 25244 25244 HASH JOIN RIGHT OUTER (cr=82317 pr=0 pw=0 time=5595368 us cost=13509 size=16723107 card=153423)
1271 1271 1271 TABLE ACCESS FULL BRAND (cr=22 pr=0 pw=0 time=315 us cost=5 size=9968 card=1246)
25244 25244 25244 HASH JOIN (cr=82295 pr=0 pw=0 time=5582567 us cost=13501 size=15495723 card=153423)
13529 13529 13529 TABLE ACCESS FULL BS_INSTANCE (cr=373 pr=0 pw=0 time=6801 us cost=63 size=161796 card=13483)
25244 25244 25244 HASH JOIN (cr=81922 pr=0 pw=0 time=5561289 us cost=13435 size=13654647 card=153423)
8984 8984 8984 TABLE ACCESS FULL BS_LOCATION_SCHEDULE (cr=247 pr=0 pw=0 time=5118 us cost=44 size=161712 card=8984)
25388 25388 25388 HASH JOIN (cr=81675 pr=0 pw=0 time=5568466 us cost=13388 size=10893033 card=153423)
12343 12343 12343 HASH JOIN (cr=77897 pr=0 pw=0 time=7626696 us cost=12679 size=1423744 card=25424)
16798 16798 16798 HASH JOIN (cr=4526 pr=0 pw=0 time=217551 us cost=848 size=1139336 card=25894)
12751 12751 12751 HASH JOIN (cr=748 pr=0 pw=0 time=21460 us cost=139 size=124439 card=4291)
5653 5653 5653 NESTED LOOPS (cr=375 pr=0 pw=0 time=4514 us cost=66 size=48328 card=3452)
1 1 1 INDEX UNIQUE SCAN ORGANISATION__PK (cr=2 pr=0 pw=0 time=22 us cost=1 size=4 card=1)(object id 98786)
5653 5653 5653 TABLE ACCESS FULL NPC_CUSTOMER_SERVICE (cr=373 pr=0 pw=0 time=3612 us cost=65 size=34520 card=3452)
32022 32022 32022 TABLE ACCESS FULL NPC_CUSTOMER_SERVICE_CIRCUIT (cr=373 pr=0 pw=0 time=13825 us cost=72 size=480330 card=32022)
324238 324238 324238 TABLE ACCESS FULL NPC_CIRCUIT_COMPONENT (cr=3778 pr=0 pw=0 time=112639 us cost=703 size=4863570 card=324238)
24918733 24918733 24918733 INDEX FAST FULL SCAN NPC_CIRCUIT_HIERARCHY_U01 (cr=73371 pr=0 pw=0 time=3349816 us cost=11418 size=292240992 card=24353416)(object id 4306730)
324238 324238 324238 TABLE ACCESS FULL NPC_CIRCUIT_COMPONENT (cr=3778 pr=0 pw=0 time=95358 us cost=703 size=4863570 card=324238)
********************************************************************************
因此慢速查询实际上使用的是不同的计划,但此计划与autotrace显示的计划不同。仍然很想知道为什么它会在两次运行后发生变化。
我想我会尝试重写查询以消除外部联接,将其拆分为由联合连接的两个单独的查询。
编辑1:添加了查询
编辑2:添加了自动跟踪输出
编辑3:从测试查询中删除(),双重,1 = 1
编辑4:添加了tkprof输出
编辑5:结果是基数反馈
答案 0 :(得分:1)
[根据乔恩·海勒的要求添加编辑作为答案]
这是由基数反馈引起的。我以为我已经测试过并消除了它,但显然弄错了。
将此添加到查询中:
select --+ opt_param('_optimizer_use_feedback' 'false')
现在始终保持快速。
答案 1 :(得分:0)
我会捅这个。
使用您提供的信息,我有以下观察结果:
1 - 您可以使用索引提示
当SQL很慢时,它不会以相同的方式访问以下表: - npc_circuit_component - npc_circuit_hierarchy
访问这些表时未使用NPC_CIRCUIT_COMPONENT_I01和NPC_CIRCUIT_HIERARCHY_I02索引。这些都会在你的解释计划中显示出来。
此处的解决方案(不修改您的查询)是使用索引提示强制一直使用此索引。
/*+ index(ch npc_circuit_hierarch_i02) */
/*+ index(cc npc_circuit_component_i01) */
2 - 重建索引或收集统计数据
如果您还没有这样做,可能需要收集统计信息或重建上述索引,以便在使用提示之前对其进行更新。
3 - 查询本身
需要提示通常意味着查询的编写方式可能存在问题。虽然在不完全理解数据模型的情况下我无法掌握数据库表中的内容,但本节可能写得更好:
bsdb.bs_instance si
left outer join scdb.brand br
on br.id = si.brand_id
join tdb.organisation o
on o.org_code = coalesce(br.brand_org_code, si.client_org_code)
and o.org_code = 2421
组织代码在这里是硬编码的,可能会使组织表的使用变得多余。你提到删除后的LEFT OUTER JOIN将使它运行得更快。您可以使用WHERE:
重写它WHERE CASE WHEN si.brand_id IS NULL THEN
si.client_org_code
ELSE
SELECT br.brand_org_code FROM brand br
WHERE br.id = si.brand_id
END = 2421 -- Ord Code
这只是我的头脑,但这避免了必须使用左外连接并且还删除了coalesce的使用,这将使brand_org_code或client_org_code列上的任何索引变得多余。
无论如何......不确定这是否有帮助。希望它能做到。祝你好运!
如果此处有任何错误,请更正我的理解。
答案 2 :(得分:0)
您的查询存在许多问题:
COALESCE
而不是仅仅明确检查NULL
。这可能会对索引的使用产生负面影响。请注意,这些过滤器对应于计划中的全表扫描。LEFT JOIN
后跟几个内部JOIN
。目前还不清楚你的意图是什么(至少在15分钟内没有盯着它)。对于所有LEFT JOIN
ed表列,NULL
仍然包含JOIN
找不到匹配项的行,如果以下{{1}中没有匹配项,则不在结果集中ed table,还是其他什么?JOIN
一些表格。您正在过滤到特定的JOIN
,并且您从不使用org_code
中的列,因此该连接不会完成任何操作。 tdb.organisation
未在任何地方引用,因此连接只是对该列中最多有效数据值的简单过滤。如果相关列是DB强制外键,则它是多余的。tdb.loc_site_code
条件而不是JOIN
子句中。这使得阅读和理解变得更加困难。我建议完全重写查询并查看其执行情况。试试这个:
WHERE
很多更容易理解:
select distinct
cc2.circuit_id as circuit_id,
cc2.circuit_component_id as component_circuit_id
from bsdb.bs_instance si
join bsdb.bs_location_schedule ls on ls.bs_instance_id = si.id
join npc.npc_customer_service cs on cs.bs_location_schedule_id = ls.id
join npc.npc_customer_service_circuit csc on csc.customer_service_id = cs.customer_service_id
join npc.npc_circuit_component cc on cc.circuit_id = csc.circuit_id
join npc.npc_circuit_hierarchy ch on ch.sub_circuit_id = cc.circuit_component_id
join npc.npc_circuit_component cc2 on cc2.circuit_id = ch.master_circuit_id
-- join tdb.loc_site_code lsc on lsc.id = ls.site_code_id -- Uncomment if ls.site_code_id isn't a foreign key
left outer join scdb.brand br on br.id = si.brand_id
where
coalesce(br.brand_org_code, si.client_org_code) = 2421
and cs.circuit_status_id in (1, 2, 6)
and (ls.terminated_date IS NULL OR ls.terminated_date >= sysdate)
and (csc.end_date IS NULL OR csc.end_date >= sysdate)
and (cc.end_date IS NULL OR cc.end_date >= sysdate)
and (cc2.end_date IS NULL OR cc2.end_date >= sysdate)
-- and ls.site_code_id IS NOT NULL -- Uncomment if site_code_id is a nullable foreign key
;
子句中的所有内容。 (请注意,这不会对性能产生负面影响。数据库足够聪明,可以确定它可以在WHERE
之前执行静态过滤。)JOIN
项检查,而不是使用可能阻止计划程序使用索引的NULL
。COALESCE
仅限于简单的表ID列。JOIN
以明确,直接,易于遵循的顺序取得进展。他们中的大多数引用了正上方表格中的ID列。JOIN
,清楚显示哪些表的列可以全部为LEFT JOIN
。如果组织代码是一个非常有选择性的过滤器(过滤掉很多行),请尝试使用
替换NULL
coalesce(br.brand_org_code, si.client_org_code) = 2421
请注意括号。规划人员可能更有可能意识到它可以使用索引。
如果由于某种原因你真的做需要((br.brand_org_code IS NULL and si.client_org_code = 2421) or br.brand_org_code = 2421)
并且在这个特定查询中没有引用这些列,请将上面的内容转换为子查询并在之后加入 所有其他过滤和转换:
tdb.organisation
我还建议提出有意义的别名。有了这些别名以及它们看起来有多相似,所以很难跟踪哪个表是哪个。一些例子:
select distinct
circuit_id,
component_circuit_id
from (
select
cc2.circuit_id as circuit_id,
cc2.circuit_component_id as component_circuit_id,
coalesce(br.brand_org_code, si.client_org_code) as org_code
from bsdb.bs_instance si
join bsdb.bs_location_schedule ls on ls.bs_instance_id = si.id
join npc.npc_customer_service cs on cs.bs_location_schedule_id = ls.id
join npc.npc_customer_service_circuit csc on csc.customer_service_id = cs.customer_service_id
join npc.npc_circuit_component cc on cc.circuit_id = csc.circuit_id
join npc.npc_circuit_hierarchy ch on ch.sub_circuit_id = cc.circuit_component_id
join npc.npc_circuit_component cc2 on cc2.circuit_id = ch.master_circuit_id
-- join tdb.loc_site_code lsc on lsc.id = ls.site_code_id -- Uncomment if ls.site_code_id isn't a foreign key
left outer join scdb.brand br on br.id = si.brand_id
where
coalesce(br.brand_org_code, si.client_org_code) = 2421
and cs.circuit_status_id in (1, 2, 6)
and (ls.terminated_date IS NULL OR ls.terminated_date >= sysdate)
and (csc.end_date IS NULL OR csc.end_date >= sysdate)
and (cc.end_date IS NULL OR cc.end_date >= sysdate)
and (cc2.end_date IS NULL OR cc2.end_date >= sysdate)
-- and ls.site_code_id IS NOT NULL -- Uncomment if site_code_id is a nullable foreign key
) active_circuit_components
join tdb.organisation org on org.org_code = active_circuit_components.org_code
;
:si
bs_instance
:ls
loc_sched
:cs
cust_serv
:csc
它们更冗长,但是当您或其他开发人员回到它时,它们会使 更容易对查询产生语义感。我知道这样的短别名是常见的做法,但是对于大型查询,你是否必须回顾表格列表才能检查列是否来自你认为的表格。
答案 3 :(得分:-1)
尝试为查询运行SQL Tunning顾问,并检查所有建议。