Sql 使用PK对联接表进行全表扫描
我有点困惑,为什么对使用主键连接的简单sql查询执行完整表扫描:Sql 使用PK对联接表进行全表扫描,sql,oracle,Sql,Oracle,我有点困惑,为什么对使用主键连接的简单sql查询执行完整表扫描: SELECT max(pd.cre_dt) FROM D00ZVZ01.ZVZ_PRINT_DOCUMENT pd JOIN D00ZVZ01.ZVZ_BRIEF_REGISTRATIE br ON pd.PRINT_DOCUMENT_ID = br.PRINT_DOCUMENT_ID AND br.BRIEF_REG_GROEP_ID IN (2217, 2237, 2257); 解释显示: -----------------
SELECT max(pd.cre_dt)
FROM D00ZVZ01.ZVZ_PRINT_DOCUMENT pd
JOIN D00ZVZ01.ZVZ_BRIEF_REGISTRATIE br
ON pd.PRINT_DOCUMENT_ID = br.PRINT_DOCUMENT_ID
AND br.BRIEF_REG_GROEP_ID IN (2217, 2237, 2257);
解释显示:
----------------------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
----------------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 24 | | 283K (2)| 00:00:15 |
| 1 | SORT AGGREGATE | | 1 | 24 | | | |
|* 2 | HASH JOIN | | 677K| 15M| 14M| 283K (2)| 00:00:15 |
| 3 | INLIST ITERATOR | | | | | | |
| 4 | TABLE ACCESS BY INDEX ROWID BATCHED| ZVZ_BRIEF_REGISTRATIE | 694K| 6779K| | 17430 (1)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | ZVZ_BRIEF_REGISTRATIE_IF4 | 694K| | | 1469 (2)| 00:00:01 |
| 6 | TABLE ACCESS FULL | ZVZ_PRINT_DOCUMENT | 9567K| 127M| | 260K (1)| 00:00:14 |
----------------------------------------------------------------------------------------------------------------------------
其中,pd.PRINT\u DOCUMENT\u ID
是主键。尽管有数以百万计的记录,但我不认为这个查询会很慢。
原因是什么,以及如何改进?可能上次计算ZVZ_PRINT_文档的统计数据时,行数很少,因此Oracle认为哈希值将非常小。请尝试重新计算统计信息或使用提示:
SELECT /*+ leading(br pd) use_nl(pd)*/ max(pd.cre_dt)
FROM D00ZVZ01.ZVZ_PRINT_DOCUMENT pd
JOIN D00ZVZ01.ZVZ_BRIEF_REGISTRATIE br
ON pd.PRINT_DOCUMENT_ID = br.PRINT_DOCUMENT_ID
AND br.BRIEF_REG_GROEP_ID IN (2217, 2237, 2257);
可能上次计算ZVZ_PRINT_文档的统计数据时,行数非常少,因此Oracle认为哈希值将非常小。请尝试重新计算统计信息或使用提示:
SELECT /*+ leading(br pd) use_nl(pd)*/ max(pd.cre_dt)
FROM D00ZVZ01.ZVZ_PRINT_DOCUMENT pd
JOIN D00ZVZ01.ZVZ_BRIEF_REGISTRATIE br
ON pd.PRINT_DOCUMENT_ID = br.PRINT_DOCUMENT_ID
AND br.BRIEF_REG_GROEP_ID IN (2217, 2237, 2257);
这会给你一个不同的计划吗
SELECT max(pd.cre_dt)
FROM D00ZVZ01.ZVZ_PRINT_DOCUMENT pd
JOIN D00ZVZ01.ZVZ_BRIEF_REGISTRATIE br
ON pd.PRINT_DOCUMENT_ID = br.PRINT_DOCUMENT_ID
WHERE br.BRIEF_REG_GROEP_ID IN (2217, 2237, 2257);
如果是这样的话,那么你想在索引中添加简短的\u REG\u GROEP\u ID。这会给你一个不同的计划吗
SELECT max(pd.cre_dt)
FROM D00ZVZ01.ZVZ_PRINT_DOCUMENT pd
JOIN D00ZVZ01.ZVZ_BRIEF_REGISTRATIE br
ON pd.PRINT_DOCUMENT_ID = br.PRINT_DOCUMENT_ID
WHERE br.BRIEF_REG_GROEP_ID IN (2217, 2237, 2257);
如果是这样,那么您希望将简短的\u REG\u GROEP\u ID添加到索引中。优化程序估计,它将使用索引从ZVZ\u简短的\u注册中访问三个简短的\u REG\u GROEP\u ID值的694K行,然后需要从ZVZ\u打印\u文档中获取相应的详细信息。694K单个索引查找非常多(考虑到它必须对每个索引进行索引,然后使用rowid以循环方式访问表694K次),并且它计算出只需读取ZVZ_PRINT_文档一次并在单个散列联接中处理两个集合所需的工作量就会减少。索引查找通常适用于小数据量 如果你提示它使用索引,它会更快吗 执行计划中的行估算是否正确?每个表中有多少行,您将实际读取多少行 您的Oracle版本是什么?您是否启用了自适应功能
有点奇怪的是,您的查询没有
WHERE
子句,而是在内部联接中包含一个过滤条件。我希望优化器会将其重写为WHERE
谓词,但我仍然希望试验它是否会影响计划。优化器估计,它将使用索引从ZVZ_BRIEF_注册中访问694K行,以获取三个BRIEF_REG_GROEP_ID值,然后需要从ZVZ_PRINT_文档中获取相应的详细信息。694K单个索引查找非常多(考虑到它必须对每个索引进行索引,然后使用rowid以循环方式访问表694K次),并且它计算出只需读取ZVZ_PRINT_文档一次并在单个散列联接中处理两个集合所需的工作量就会减少。索引查找通常适用于小数据量
如果你提示它使用索引,它会更快吗
执行计划中的行估算是否正确?每个表中有多少行,您将实际读取多少行
您的Oracle版本是什么?您是否启用了自适应功能
有点奇怪的是,您的查询没有
WHERE
子句,而是在内部联接中包含一个过滤条件。我希望乐观主义者会将其重写为WHERE
谓词,但我仍然希望进行实验,看看它是否影响了计划。ZVZ\u PRINT\u文档的大小(字节)是多少,PK索引的聚类因子是多少?这可能是由于索引访问的选择性不是很好,因此即使通过索引也会读取大量数据。ZVZ_PRINT_文档的大小(以字节为单位)是多少?PK索引的聚类系数是多少?这可能是由于索引访问的选择性不是很好,因此即使通过索引也会读取大量数据。对690k行使用
不太可能提高性能。15mb散列大小不是很大,遗憾的是,这并没有提高检索速度。对690k行使用\u NL
不太可能提高性能。15mb的散列大小不是很大,很遗憾这并没有提高检索速度。您好,很抱歉回复太晚。这给了我同样的计划。简短的\u REG\u GROEP\u ID有一个索引,这个查询本身(没有连接)执行得很好。@html\u程序员您需要一个关于两列组合的索引。。。列上有两个索引无助于加快此查询。您好,很抱歉回复太晚。这给了我同样的计划。简短的\u REG\u GROEP\u ID有一个索引,这个查询本身(没有连接)执行得很好。@html\u程序员您需要一个关于两列组合的索引。。。列上有两个索引无助于加快查询速度。您好,我检查了行数,它们是正确的。也就是说,694k行距离。。。在关于ZVZ_简短登记(无连接)的条款中,以及ZVZ_打印文件中的956k行。我试图添加WHERE子句而不是AND(在连接上),但这确实给出了相同的结果。问题是,他们需要REST调用来检索此状态,但这将花费太长时间,并且浏览器可能会在ajax请求时超时。实际上,ZVZ_PRINT_文档的估计值为9567K行,即956M左右,其中677K行使用率略低于10%。也许677K索引查找会更快,也许不会。这就是为什么我想知道,如果你让它使用带有提示的索引,它是否真的更快。在CRE_DT中添加一个索引有助于从>2m减少到大约24秒。我尝试了不同的提示策略,但无法进一步减少。谢谢你的建议,我认为24秒应该可以在内部使用。这是一个索引吗?这样就不用访问表了。您好,我检查了行数,它们是正确的。也就是说,694k行距离。。。在关于ZVZ_简短登记(无连接)的条款中,以及ZVZ_打印文件中的956k行。我试图添加WHERE子句而不是AND(在连接上),但这确实给出了相同的结果。