我使用了这个查询
SELECT grirno, grirdate
FROM grirmain
WHERE grirno NOT IN (SELECT grir
FROM billcrown
WHERE grir IS NOT NULL)
但需要578毫秒。请优化此查询
答案 0 :(得分:0)
大多数情况下,使用NOT IN
会降低查询性能。
对于您的情况,我建议您使用两套MINUS
作为:
SELECT grirno, grirdate
FROM grirmain
MINUS
SELECT grirno, grirdate
FROM grirmain
WHERE grirno IN (SELECT grir
FROM billcrown
WHERE grir IS NOT NULL);
通过这种方式,查询可能会使列grirno上的索引受益(如果它是主键列,它自然会有索引),而在NOT IN
的情况下,索引不能使用。< / p>
答案 1 :(得分:0)
我会将查询编写为foreach
并添加索引:
not exists
您想要的索引位于SELECT m.grirno, m.grirdate
FROM grirmain m
WHERE NOT EXISTS (SELECT 1
FROM billcrown bc
WHERE bc.grir = m.grirno
) ;
。
答案 2 :(得分:0)
提供更多信息会很有帮助,因为根据没有表和索引定义以及数据量的单个查询,很难说半秒是否是最佳的。
通常,除非子查询可能返回空值(即,如果billcrown.grir
可以为空并且您没有指定where grir is not null
)或者您有一些非标准设置,则{{1} }和[NOT] EXISTS
版本是相同的,并且将具有相同的执行计划,并将其中一个重写为另一个是浪费时间。
测试设置(Oracle 12.2,但这一切都没有改变):
[NOT] IN
create table grirmain
( grirno integer generated always as identity constraint grimain_pk primary key
, grirdate date default on null sysdate );
create table billcrown
( grir constraint billcrown_grimain_fk references grirmain
, dummy varchar2(50) );
insert into grirmain (grirdate) select sysdate - dbms_random.value(0,10000)
from dual connect by rownum <= 1e6;
insert into billcrown (grir, dummy)
select grirno, dbms_random.string('A',50)
from grirmain
where mod(grirno,10) = 1
union all
select null, dbms_random.string('A',50)
from grirmain
where rownum <= 1000;
commit;
begin
dbms_stats.gather_table_stats(user,'grirmain');
dbms_stats.gather_table_stats(user,'billcrown');
end;
/
版本的执行计划(运行几次以消除缓存问题 - 在大约7秒内完成):
not in
SQL> set autotrace trace exp stat
SQL> r
1 select grirno, grirdate
2 from grirmain
3 where grirno not in
4 ( select grir
5 from billcrown
6* where grir is not null )
900000 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 56519876
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 901K| 15M| | 2194 (1)| 00:00:01 |
|* 1 | HASH JOIN RIGHT ANTI| | 901K| 15M| 1664K| 2194 (1)| 00:00:01 |
|* 2 | TABLE ACCESS FULL | BILLCROWN | 100K| 488K| | 239 (1)| 00:00:01 |
| 3 | TABLE ACCESS FULL | GRIRMAIN | 1000K| 12M| | 687 (1)| 00:00:01 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("GRIRNO"="GRIR")
2 - filter("GRIR" IS NOT NULL)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
63225 consistent gets
0 physical reads
0 redo size
24221330 bytes sent via SQL*Net to client
660596 bytes received via SQL*Net from client
60001 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
900000 rows processed
版本的执行计划:
NOT EXISTS
向SQL> select grirno, grirdate
2 from grirmain
3 where not exists
4 ( select grir
5 from billcrown
6 where grir is not null
7 and grir = grirno );
900000 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 56519876
------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 901K| 15M| | 2194 (1)| 00:00:01 |
|* 1 | HASH JOIN RIGHT ANTI| | 901K| 15M| 1664K| 2194 (1)| 00:00:01 |
|* 2 | TABLE ACCESS FULL | BILLCROWN | 100K| 488K| | 239 (1)| 00:00:01 |
| 3 | TABLE ACCESS FULL | GRIRMAIN | 1000K| 12M| | 687 (1)| 00:00:01 |
------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("GRIR"="GRIRNO")
2 - filter("GRIR" IS NOT NULL)
Statistics
----------------------------------------------------------
1 recursive calls
0 db block gets
63225 consistent gets
0 physical reads
0 redo size
24221330 bytes sent via SQL*Net to client
660596 bytes received via SQL*Net from client
60001 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
900000 rows processed
添加索引允许索引快速全扫描而不是表扫描(这样做的好处将取决于表中有多少块 - 在我的示例中,它只有两个小列所以好处很小):
bill crown.grir
答案 3 :(得分:-2)
虽然这取决于您的数据大小和索引。您可以根据需要在where子句上创建索引作为缩略图规则 尝试使用以下选项
run_dir=/var/run/myscript # change the name as appropriate
check_step() {
step=$1
step_file=$run_dir/$step.step.done
if [ ! -f "$step_file" ]; then
return 0
else
echo "Step $step skipped"
return 1
fi
}
step_done() {
touch "$run_dir/$1.step.done" && echo finished step $1
}
mkdir -p "$run_dir"
check_step upgrade && freebsd-update upgrade -r 11.1-RELEASE && step_done upgrade
check_step install1 && freebsd-update install && step_done install1
shutdown -r now
check_step install2 && freebsd-update install && step_done install2