for*_*rtm 1 java sql oracle spring-jdbc spring-batch
考虑具有主键的表作为columnd"id"
必须查询一系列id为[1,2,3,4 ......]
有2个选项 -
1)
Select * from Table where id = 1;
Select * from Table where id = 2;
Select * from Table where id = 3;
Select * from Table where id = 4;
Run Code Online (Sandbox Code Playgroud)
2)
Select * from Table where id in ( 1, 2, 3, 4 );
Run Code Online (Sandbox Code Playgroud)
对于Oracle而言,这两者中的哪一个在性能方面更好,并且使用Spring JDBC模板来实现持久性.假设数据集1,2,3,4将在java数据结构的限制范围内,请从应用程序的角度考虑内存约束.
它使用数据库连接池.
我宁愿使用第二个查询,因为它只查询数据库一次.除此之外,您只需连接数据库一次.
请记住,数据库连接成本很高(消耗大量资源).
要备份JW和a_horse_with_no_name的语句,这里是一个测试,都使用相同的连接,因此这里忽略连接(池)问题.
首先使用主键创建表并收集优化程序的统计信息:
SQL> create table mytable
2 as
3 select level id
4 , lpad('*',1000,'*') filler
5 from dual
6 connect by level <= 10000
7 /
Table created.
SQL> alter table mytable add constraint my_pk primary key (id)
2 /
Table altered.
SQL> exec dbms_stats.gather_table_stats(user,'mytable')
PL/SQL procedure successfully completed.
Run Code Online (Sandbox Code Playgroud)
接下来,将所有语句放在共享池中,作为预热,切断查询的大部分输出:
SQL> select * from mytable where id = 1
2 /
ID
----------
FILLER
---------------------------------------------------------------------------------------------------------------------------------------
1
***************************************************************************************************************************************
***************************************************************************************************************************************
***************************************************************************************************************************************
***************************************************************************************************************************************
***************************************************************************************************************************************
***************************************************************************************************************************************
***************************************************************************************************************************************
*******************************************************
1 row selected.
SQL> select * from mytable where id = 2
2 /
1 row selected.
SQL> select * from mytable where id = 3
2 /
1 row selected.
SQL> select * from mytable where id = 4
2 /
1 row selected.
SQL> select * from mytable where id in (1,2,3,4)
2 /
4 rows selected.
Run Code Online (Sandbox Code Playgroud)
接下来,检查autotrace输出,以查看数据库必须执行的工作:
SQL> set autotrace traceonly
SQL> select * from mytable where id = 1
2 /
1 row selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3280897506
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1005 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| MYTABLE | 1 | 1005 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | MY_PK | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=1)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
1387 bytes sent via SQL*Net to client
448 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select * from mytable where id = 2
2 /
1 row selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3280897506
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1005 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| MYTABLE | 1 | 1005 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | MY_PK | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=2)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
1387 bytes sent via SQL*Net to client
448 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select * from mytable where id = 3
2 /
1 row selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3280897506
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1005 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| MYTABLE | 1 | 1005 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | MY_PK | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=3)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
1387 bytes sent via SQL*Net to client
448 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select * from mytable where id = 4
2 /
1 row selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 3280897506
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 1005 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| MYTABLE | 1 | 1005 | 2 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | MY_PK | 1 | | 1 (0)| 00:00:01 |
---------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("ID"=4)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
3 consistent gets
0 physical reads
0 redo size
1387 bytes sent via SQL*Net to client
448 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select * from mytable where id in (1,2,3,4)
2 /
4 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1637292604
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 4 | 4020 | 4 (0)| 00:00:01 |
| 1 | INLIST ITERATOR | | | | | |
| 2 | TABLE ACCESS BY INDEX ROWID| MYTABLE | 4 | 4020 | 4 (0)| 00:00:01 |
|* 3 | INDEX UNIQUE SCAN | MY_PK | 4 | | 3 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("ID"=1 OR "ID"=2 OR "ID"=3 OR "ID"=4)
Statistics
----------------------------------------------------------
0 recursive calls
0 db block gets
8 consistent gets
0 physical reads
0 redo size
2435 bytes sent via SQL*Net to client
448 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
4 rows processed
SQL> set autotrace off
Run Code Online (Sandbox Code Playgroud)
四次3次连续获得与8次一致获得.最后,让我们通过10,000次执行所有语句来计算两种变体:
SQL> set timing on
SQL> declare
2 v_id number;
3 v_filler varchar2(1000);
4 begin
5 for i in 1 .. 10000
6 loop
7 select *
8 into v_id, v_filler
9 from mytable
10 where id = 1
11 ;
12 select *
13 into v_id, v_filler
14 from mytable
15 where id = 2
16 ;
17 select *
18 into v_id, v_filler
19 from mytable
20 where id = 3
21 ;
22 select *
23 into v_id, v_filler
24 from mytable
25 where id = 4
26 ;
27 end loop;
28 end;
29 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.03
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:01.00
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.99
SQL> declare
2 v_id number;
3 v_filler varchar2(1000);
4 begin
5 for i in 1 .. 10000
6 loop
7 for r in (select * from mytable where id in (1,2,3,4))
8 loop
9 v_id := r.id;
10 v_filler := r.filler;
11 end loop;
12 end loop;
13 end;
14 /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.41
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.39
SQL> /
PL/SQL procedure successfully completed.
Elapsed: 00:00:00.39
SQL> set timing off
Run Code Online (Sandbox Code Playgroud)
在这里,您可以看到向数据库发送四次以上语句的开销最大.根据索引深度和聚类因子,这里和那里可能存在一些变化,但是一个查询与四个查询仍将是最大的差异.
所以,希望这个帖子的读者不再说"IN条款已经很昂贵了":-)
问候,
Rob.