并行查询允许将一个SQL SELECT语句划分为多个较小的查询,每个部分的查询并发地运行,然后会将各个部分的结果组合起来,提供最终的答案。
我们来看一个例子:
1. 执行如下一串SQL语句,创建一个叫big_table的表,期间会让你录入 1的值(想要往big_table表里面插入多少行数据),我录入的是1000万行。
create table big_table as select rownum id, a.* from all_objects a where 1=0 / alter table big_table nologging; declare l_cnt number; l_rows number := &1; begin insert /*+ append */ into big_table select rownum, a.* from all_objects a; l_cnt := sql%rowcount; commit; while (l_cnt < l_rows) loop insert /*+ APPEND */ into big_table select rownum+l_cnt, OWNER, OBJECT_NAME, SUBOBJECT_NAME, OBJECT_ID, DATA_OBJECT_ID, OBJECT_TYPE, CREATED, LAST_DDL_TIME, TIMESTAMP, STATUS, TEMPORARY, GENERATED, SECONDARY from big_table where rownum <= l_rows-l_cnt; l_cnt := l_cnt + sql%rowcount; commit; end loop; end; / alter table big_table add constraint big_table_pk primary key(id) / begin dbms_stats.gather_table_stats ( ownname => user, tabname => 'BIG_TABLE', method_opt => 'for all indexed columns', cascade => TRUE ); end; / select count(*) from big_table;
2. 查询 非并行执行态,select count(status) from big_table 所耗用时间。
explain plan for select count(status) from big_table; select * from table(dbms_xplan.display);
我电脑上的执行结果如下图所示,耗用时间是6分半钟。
3. 修改表允许并行执行,重新执行解析计划
alter table big_table parallel; explain plan for select count(status) from big_table; select * from table(dbms_xplan.display);
我电脑上的执行结果如下图所示,耗时1分40。
如果自下而上地读这个计划(从ID=6开始),它显示了并行执行的具体步骤。全表扫描会分解为多个较小的扫描(第5步)。每个扫描汇总其COUNT(STATUS)值(第4步)。这些子结果将传送给并行查询协调器(第2步和第3步),它会进一步汇总这些结果(第1步),并输出答案。