Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 使用PK对联接表进行全表扫描_Sql_Oracle - Fatal编程技术网

Sql 使用PK对联接表进行全表扫描

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); 解释显示: -----------------

我有点困惑,为什么对使用主键连接的简单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);
解释显示:

----------------------------------------------------------------------------------------------------------------------------
| 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(在连接上),但这确实给出了相同的结果。