Oracle 为什么优化器计划与实验查询运行不相关?
假设我们有以下问题: 给定一个具有一列“X”的表,其中包含一些带有随机变量的行 从1到100的整数:Oracle 为什么优化器计划与实验查询运行不相关?,oracle,database-performance,oracle12c,sqlperformance,cost-based-optimizer,Oracle,Database Performance,Oracle12c,Sqlperformance,Cost Based Optimizer,假设我们有以下问题: 给定一个具有一列“X”的表,其中包含一些带有随机变量的行 从1到100的整数: CREATE TABLE xtable(x) AS SELECT ceil(dbms_random.value * 100) FROM dual CONNECT BY level <= 1000000; 二, 三, 计划是在Oracle 12.1.0.2.0上获得的无法复制第二个计划。下面是: ----------------------------------
CREATE TABLE xtable(x) AS
SELECT ceil(dbms_random.value * 100)
FROM dual
CONNECT BY level <= 1000000;
二,
三,
计划是在Oracle 12.1.0.2.0上获得的无法复制第二个计划。下面是:
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | | | | 3648 (100)| |
| 1 | DELETE | XTABLE | | | | | |
| 2 | MERGE JOIN ANTI NA | | 999K| 26M| | 3648 (5)| 00:00:01 |
| 3 | SORT JOIN | | 1000K| 2929K| 22M| 3147 (3)| 00:00:01 |
| 4 | TABLE ACCESS FULL | XTABLE | 1000K| 2929K| | 434 (3)| 00:00:01 |
|* 5 | SORT UNIQUE | | 100 | 2500 | | 500 (16)| 00:00:01 |
| 6 | VIEW | VW_NSO_1 | 100 | 2500 | | 499 (16)| 00:00:01 |
| 7 | SORT GROUP BY | | 100 | 300 | | 499 (16)| 00:00:01 |
| 8 | TABLE ACCESS FULL| XTABLE | 1000K| 2929K| | 434 (3)| 00:00:01 |
-------------------------------------------------------------------------------------------
请解释为什么我不能信任案例2中的优化器计划
永远不要相信优化器。国会预算办公室95%是正确的,但你不知道哪5%是错误的
典型的问题是,使用EXPLAIN plan显示的执行计划不等于执行所使用的计划。你没有说你是如何得到这个计划的
如有疑问,请使用长时间运行的查询来查看实际计划和有问题的部分
是什么导致优化器忽略线性复杂度和指数复杂度之间的明显差异
请参见上文,忘记计划的成本比较。处理整个表时要避免的是嵌套循环处理。
这正是案例3中发生的情况
| 3 | NESTED LOOPS SEMI | | 50000| 300000 | 278208956 | 03:01:08|
| 4 | TABLE ACCESS FULL |XTABLE | 1000000| 3000000 | 280 | 00:00:01|
| 5 | TABLE ACCESS BY ROWID RANGE |XTABLE | 50000| 150000 | 278 | 00:00:01|
您想看到排序和散列连接这是计划1显示的内容
在我看来,计划2不会随着重复记录的数量而扩展,只需在一个表中每行尝试两次,看看是否得到与案例3相同的运行时间。
优化器无法估计重复记录的数量,因此防御性地估计了较高的数量,从而导致了较高的成本
最后一句话——理论上说你不应该观察线性行为,但最好是在*logn上
最后一句话-对于DUP移除,您的测试数据不现实。通常,您有一个包含少量DUP的大表。在您的设置中,除100条记录外,所有记录都是重复的
删除的成本在查找DUP的成本中占主导地位,因此您可以观察线性行为
试一试
CREATE TABLE xtable(x) AS
SELECT ceil(dbms_random.value * 100000000)
FROM dual
CONNECT BY level <= 1000000;
select count(*) total, count(*)- count(distinct x) to_be_deleted from xtable;
TOTAL TO_BE_DELETED
---------- -------------
1000000 5083
因此,您将删除0.5%的记录。现在进行缩放,您将完全观察其他模式。在案例2中,当您说不能信任优化器计划时,您的意思是什么?是什么让你认为2和3的执行计划是相似的?执行计划3有两个完整的表扫描,由嵌套的半循环连接,然后进行过滤。执行计划2有一个排序,后跟一个筛选器,然后使用该排序筛选完整表扫描的结果。这与第一个执行计划非常相似,IMOH.@ Boeistor,我考虑列值、字节、成本、时间的总值的相似性。令人惊讶的是,它们几乎是一样的,当我们用不同数量的行填充表格时,它们是同步变化的:1000,10000,…,10000加上一个用于准备好的Q。请提供Oracle版本,并将谓词信息添加到解释计划中。看看如何获取信息。它看起来像我期望的那样。似乎我的数据库有一个异常或棘手的设置或其他东西。现在真的没关系了。困扰我的是如何确定DB执行查询的方式。我很困惑,因为我以前从未遇到过这样的问题,并且认为解释计划至少大致显示了查询运行时的预期结果。@diziaq您有什么Oracle版本?我已经在11和12中测试了它,当我们不计算成本时,执行计划是相同的。你永远不会确定。您可以使用SQL计划基线我昨天和今天多次在Oracle 12.1上使用不同的实例获得计划。问了这个问题后,我在Oracle 11.2上尝试了相同的查询,正如您所做的,我无法重现我所问的计划。看起来是个意外,但我想知道是什么原因造成的。谢谢你提供的有用信息。我同意On*logn,但令人惊讶的是结果是100000行:1.65秒;1000000行-15.8行;10000000-138.6秒;甚至比预期的还要低。“我认为低质量的测试数据抵消了常见的理论影响。”迪齐亚克补充道
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | DELETE STATEMENT | | | | | 3648 (100)| |
| 1 | DELETE | XTABLE | | | | | |
| 2 | MERGE JOIN ANTI NA | | 999K| 26M| | 3648 (5)| 00:00:01 |
| 3 | SORT JOIN | | 1000K| 2929K| 22M| 3147 (3)| 00:00:01 |
| 4 | TABLE ACCESS FULL | XTABLE | 1000K| 2929K| | 434 (3)| 00:00:01 |
|* 5 | SORT UNIQUE | | 100 | 2500 | | 500 (16)| 00:00:01 |
| 6 | VIEW | VW_NSO_1 | 100 | 2500 | | 499 (16)| 00:00:01 |
| 7 | SORT GROUP BY | | 100 | 300 | | 499 (16)| 00:00:01 |
| 8 | TABLE ACCESS FULL| XTABLE | 1000K| 2929K| | 434 (3)| 00:00:01 |
-------------------------------------------------------------------------------------------
| 3 | NESTED LOOPS SEMI | | 50000| 300000 | 278208956 | 03:01:08|
| 4 | TABLE ACCESS FULL |XTABLE | 1000000| 3000000 | 280 | 00:00:01|
| 5 | TABLE ACCESS BY ROWID RANGE |XTABLE | 50000| 150000 | 278 | 00:00:01|
CREATE TABLE xtable(x) AS
SELECT ceil(dbms_random.value * 100000000)
FROM dual
CONNECT BY level <= 1000000;
select count(*) total, count(*)- count(distinct x) to_be_deleted from xtable;
TOTAL TO_BE_DELETED
---------- -------------
1000000 5083