我是 Oracle 的长期用户/开发人员。 Oracle 版本是 19c.
场景是,我有一个读取表 A 的查询得到一个连接到表 B 的唯一标识符。
select A.unique_id, B.*
from A
inner join B on B.unique_id = A.unique_id
where A.unique_id = 123;
查询运行很快,解释计划使用 B.unique_id 的索引显示它。
但是如果我想查看所有行;
select A.unique_id, B.*
from A
inner join B on B.unique_id = A.unique_id;
它永远运行,解释计划说它正在进行全表扫描。
我不清楚发生了什么。这似乎是我一定错过的一个基本问题。
谁能解释一下;
编辑:
A 表目前有大约 700 万行。表 B 有大约 2800 万行
用where子句解释计划;
<TABLE class="TreeTableWidget" border=0 cellpadding=0 cellspacing=0 width=100% bgcolor=#efefef><tr><td>
<!-- ..........................data begin........................... -->
<TABLE class=TreeTableWidget border=0 cellspacing=0 cellpadding=1 align=center width=100%" bgcolor=#ffffff>
<tr class="TableCell">
<td valign=top bgcolor=#bbbbbb> <font color=#444477>OPERATION</font> </td>
<td valign=top bgcolor=#aaaaaa> <font color=#444477>OBJECT_NAME</font> </td>
<td valign=top bgcolor=#bbbbbb> <font color=#444477>OPTIONS</font> </td>
<td valign=top bgcolor=#aaaaaa> <font color=#444477>CARDINALITY</font> </td>
<td valign=top bgcolor=#bbbbbb> <font color=#444477>COST</font> </td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-1><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> SELECT STATEMENT </td></tr></table></font></td>
<td width=11% valign=top bgcolor=#dfdfdf >   </td>
<td width=11% valign=top bgcolor=#dfd5d1 >   </td>
<td width=11% valign=top bgcolor=#dfdfdf > 1 </font></td>
<td width=11% valign=top bgcolor=#dfd5d1 > 3 </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-1><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/join.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> NESTED LOOPS </td></tr></table></font></td>
<td width=11% valign=top bgcolor=#ffffdf >   </td>
<td width=11% valign=top bgcolor=#ffffd2 >   </td>
<td width=11% valign=top bgcolor=#ffffdf > 1 </font></td>
<td width=11% valign=top bgcolor=#ffffd2 > 3 </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/index.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> INDEX </td></tr></table></font></td>
<td width=11% valign=top bgcolor=#dfdfdf ><font size=-1> IND_ABSGEOCODE </font></td>
<td width=11% valign=top bgcolor=#dfd5d1 ><font size=-1> UNIQUE SCAN </font></td>
<td width=11% valign=top bgcolor=#dfdfdf > 1 </font></td>
<td width=11% valign=top bgcolor=#dfd5d1 > 2 </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/index.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> INDEX </td></tr></table></font></td>
<td width=11% valign=top bgcolor=#ffffdf ><font size=-1> ABSHIST_RECORD_SEQ </font></td>
<td width=11% valign=top bgcolor=#ffffd2 ><font size=-1> UNIQUE SCAN </font></td>
<td width=11% valign=top bgcolor=#ffffdf > 1 </font></td>
<td width=11% valign=top bgcolor=#ffffd2 > 1 </font></td>
</tr>
</table>
<!-- ..........................data end........................... -->
</td></tr></TABLE>
没有where子句的解释计划;
<TABLE class="TreeTableWidget" border=0 cellpadding=0 cellspacing=0 width=100% bgcolor=#efefef><tr><td>
<!-- ..........................data begin........................... -->
<TABLE class=TreeTableWidget border=0 cellspacing=0 cellpadding=1 align=center width=100%" bgcolor=#ffffff>
<tr class="TableCell">
<td valign=top bgcolor=#bbbbbb> <font color=#444477>OPERATION</font> </td>
<td valign=top bgcolor=#aaaaaa> <font color=#444477>OBJECT_NAME</font> </td>
<td valign=top bgcolor=#bbbbbb> <font color=#444477>OPTIONS</font> </td>
<td valign=top bgcolor=#aaaaaa> <font color=#444477>CARDINALITY</font> </td>
<td valign=top bgcolor=#bbbbbb> <font color=#444477>COST</font> </td>
<td valign=top bgcolor=#aaaaaa> <font color=#444477>OBJECT_NODE</font> </td>
<td valign=top bgcolor=#bbbbbb> <font color=#444477>OTHER_TAG</font> </td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-2><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> SELECT STATEMENT </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#dfdfdf >   </td>
<td width=7% valign=top bgcolor=#dfd5d1 >   </td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> 6787518 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> 21297 </font></td>
<td width=7% valign=top bgcolor=#dfdfdf >   </td>
<td width=7% valign=top bgcolor=#dfd5d1 >   </td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-2><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> PX COORDINATOR </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#ffffdf >   </td>
<td width=7% valign=top bgcolor=#ffffd2 >   </td>
<td width=7% valign=top bgcolor=#ffffdf >   </td>
<td width=7% valign=top bgcolor=#ffffd2 >   </td>
<td width=7% valign=top bgcolor=#ffffdf >   </td>
<td width=7% valign=top bgcolor=#ffffd2 >   </td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-1><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> PX SEND </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-2> SYS.:TQ10002 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-2> QC (RANDOM) </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> 6787518 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> 21297 </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> :Q1002 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> P->S </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-1><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/join.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> HASH JOIN </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#ffffdf >   </td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> BUFFERED </font></td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> 6787518 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> 21297 </font></td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> :Q1002 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> PCWP </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-2><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> PX RECEIVE </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#dfdfdf >   </td>
<td width=7% valign=top bgcolor=#dfd5d1 >   </td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> 6930390 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> 13149 </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> :Q1002 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> PCWP </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-1><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> PX SEND </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-2> SYS.:TQ10000 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-2> HYBRID HASH </font></td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> 6930390 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> 13149 </font></td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> :Q1000 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> P->P </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-2><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> STATISTICS COLLECTOR </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#dfdfdf >   </td>
<td width=7% valign=top bgcolor=#dfd5d1 >   </td>
<td width=7% valign=top bgcolor=#dfdfdf >   </td>
<td width=7% valign=top bgcolor=#dfd5d1 >   </td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> :Q1000 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> PCWC </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-1><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> PX BLOCK </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#ffffdf >   </td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> ITERATOR </font></td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> 6930390 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> 13149 </font></td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> :Q1000 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> PCWC </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-2><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/table.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> TABLE ACCESS </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> ABSHIST </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> FULL </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> 6930390 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> 13149 </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> :Q1000 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> PCWP </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-2><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> PX RECEIVE </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#ffffdf >   </td>
<td width=7% valign=top bgcolor=#ffffd2 >   </td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> 6787518 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> 8147 </font></td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> :Q1002 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-1> PCWP </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-1><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> PX SEND </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-2> SYS.:TQ10001 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-2> HYBRID HASH </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> 6787518 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> 8147 </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> :Q1001 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-2> PARALLEL_FROM_SERIAL </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-2><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/gray.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> PX SELECTOR </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#ffffdf >   </td>
<td width=7% valign=top bgcolor=#ffffd2 >   </td>
<td width=7% valign=top bgcolor=#ffffdf >   </td>
<td width=7% valign=top bgcolor=#ffffd2 >   </td>
<td width=7% valign=top bgcolor=#ffffdf ><font size=-1> :Q1001 </font></td>
<td width=7% valign=top bgcolor=#ffffd2 ><font size=-2> SINGLE_COMBINED_WITH_CHILD </font></td>
</tr>
<tr>
<td width=45% valign=top bgcolor=#ffffff ><font size=-1><table width=100% border=0 cellspacing=0 cellpadding=0><tr><td width=1%><table CELLSPACING=0 cellpadding=0><tr><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td> </td><td><IMG SRC="images/minus.gif" wWIDTH=16 hHEIGHT=16 BORDER=0><IMG SRC="images/index.png" wWIDTH=16 hHEIGHT=16 BORDER=0></td><tr></table></td> <td width=99%> INDEX </td></tr></table></font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-2> IND_ABSGEOCODE </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-2> RANGE SCAN </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> 6787518 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-1> 8147 </font></td>
<td width=7% valign=top bgcolor=#dfdfdf ><font size=-1> :Q1001 </font></td>
<td width=7% valign=top bgcolor=#dfd5d1 ><font size=-2> SINGLE_COMBINED_WITH_PARENT </font></td>
</tr>
</table>
<!-- ..........................data end........................... -->
</td></tr></TABLE>
Oracle 会选择它认为最好的方案。有时会使用索引,有时会使用全表扫描。所以这是很正常的行为,尤其是在删除谓词时。鉴于您当前的查询没有 123 谓词,除非 table_A 与 table_B 相比非常小,否则使用全扫描的散列连接实际上是最好的方法。你确实 not 想尝试强制它使用索引。
至于为什么它“永远占用”,您应该得到一个执行计划并查询
v$active_session_history
您的SQLID以查看发生了什么以及它在哪里花费时间,或者向您的DBA寻求帮助。
没有看到任何东西,我最初的猜测是:
您当然可以通过使用并行性更快地获得散列连接:
select /*+ parallel(8) */ A.unique_id, B.*
from A
inner join B on B.unique_id = A.unique_id;
也许还与 DBA 合作分配更多 PGA 以减少临时空间工作区,但这对整体运行时间没有多大好处,因为将所有这些结果取回给您的客户端需要更长的时间,这就是受网络延迟和客户端提取调用大小的限制。
Oracle 不使用索引的另一个非常常见的原因是数据库统计信息丢失或过时。
检查上次分析表和索引的时间:
SELECT table_name, num_rows, last_analyzed FROM user_tables WHERE table_name = 'my_table';
和
SELECT index_name, num_rows, last_analyzed FROM user_indexes WHERE index_name = 'my_index';
如果您正在使用的数据库对象的统计信息是陈旧的,您应该强制 Oracle 生成新的统计信息,例如:
EXEC DBMS_STATS.gather_table_stats('SCOTT', 'EMPLOYEES', estimate_percent => 15, cascade => TRUE);
基于成本的优化器 (CBO) 和数据库统计 在进入官方 Oracle 文档 之前提供了一个很好的介绍。