一条语句还是两条语句

 

查询一组数据,是尽可能的减少查询次数,使用少量的查询语句快呢?还是每个数据单独对应查询语句好?
 
大家看到上面的问题后,也许很快就有了自己的结论。
 
比如:求一类案件不同结论的数量各是多少?很多同学都会用到以下查询。
 
select 案件结论, count(*)
 from 案件表
 group by 案件结论
 
这样不管案件有多少种结论都能用上面的查询一次完成,而且速度是理想的。那么是不是所有的查询都是尽可能的精简呢?
 
下面的例子是从一个表上取某字段的最大值和最小值。
 
先别急下结论,我们通过Sybase ASE 做个实验,看看实际的情况吧。
 
测试
测试环境

测试表
K_ZNXT..B_STBD_XS
数据量
120184
索引
对字段 ZXXQ

 
说明:计划任务及IO读取只列出了关键部分。
 
有索引的情况
一条语句读取
select max(ZXXQ), min(ZXXQ) from K_ZNXT..B_STBD_XS
 
        FROM TABLE
            K_ZNXT..B_STBD_XS
        Nested iteration.
        Index : I_STBD_XS_ZXXQ
        Forward scan.
        Positioning at index start.
 
logical reads: (regular=1766 apf=0 total=1766)
physical reads: (regular=0 apf=0 total=0)
 
 
分两次读取
select max(ZXXQ) from K_ZNXT..B_STBD_XS
 
        FROM TABLE
            K_ZNXT..B_STBD_XS
        Nested iteration.
        Index : I_STBD_XS_ZXXQ
        Backward scan.
        Positioning at index end.
        Scanning only up to the first qualifying row.
 
logical reads: (regular=3 apf=0 total=3)
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
 
select min(ZXXQ) from K_ZNXT..B_STBD_XS
 
        FROM TABLE
            K_ZNXT..B_STBD_XS
        Nested iteration.
        Index : I_STBD_XS_ZXXQ
        Forward scan.
        Positioning at index start.
        Scanning only up to the first qualifying row.
 
logical reads: (regular=723 apf=0 total=723)
physical reads: (regular=0 apf=0 total=0), apf IOs used=0
 
结论说明

比较项目
一句读取
两句读取
扫描方式
索引扫描
索引扫描
扫描方向
往前扫描
往前扫描 + 往后扫描
扫描条数
全部扫描
正序第一条 + 倒序第一条
IO 逻辑读
1766
3 + 723
IO 物理读
0
0

 
从数据上来看“两句读取”要用到的资源少一些,应该会执行快一些。
从实验的具体结果来看也是如此。
当数据都已加载到内存中,即IO物理读为0时,从执行时间来看差异性不大。
当数据都在磁盘中,会先把数据从磁盘加载到内存,这时再来看执行时间,差异性就明显了。
 
无索引的情况
一条语句读取
select max(ZXXQ), min(ZXXQ) from K_ZNXT..B_STBD_XS
 
        FROM TABLE
            K_ZNXT..B_STBD_XS
        Nested iteration.
        Table Scan.
        Forward scan.
        Positioning at start of table.
 
logical reads: (regular=7395 apf=0 total=7395)
physical reads: (regular=0 apf=0 total=0)
 
分两次读取
 
select min(ZXXQ) from K_ZNXT..B_STBD_XS
 
        FROM TABLE
            K_ZNXT..B_STBD_XS
        Nested iteration.
        Table Scan.
        Forward scan.
        Positioning at start of table.
 
logical reads: (regular=7395 apf=0 total=7395)
physical reads: (regular=0 apf=0 total=0)
 
select max(ZXXQ) from K_ZNXT..B_STBD_XS
 
        FROM TABLE
            K_ZNXT..B_STBD_XS
        Nested iteration.
        Table Scan.
        Forward scan.
        Positioning at start of table.
 
 
logical reads: (regular=7395 apf=0 total=7395)
physical reads: (regular=0 apf=0 total=0)
 
 
结论说明

比较项目
一句读取
两句读取
扫描方式
全表扫描
全表扫描
扫描方向
往前扫描
往前扫描 + 往前扫描
扫描条数
全部扫描
全部扫描 + 全部扫描
IO 逻辑读
7395
7395 + 7395
IO 物理读
0
0

 
没有索引的情况下,全表扫描需要的资源陡然增加。每次查询都会用到全表扫描,结论自然也就显而易见了。
 
 
总结
执行SQL速度快慢得靠分析查询计划和IO读取的数据来说话。
在其他不同的条件下,同样的SQL也有不同的查询计划。
在时间允许的情况下,需要对SQL逐条分析,使其达到最优。
 
Oracle 中也有类似的情况,这里不再多举例子了。有兴趣的同学自己再试试吧。
附录
控制Session查询的输出

命令
说明
set statistics time on
输出执行时间
set statistics io on
输出IO量
set showplan on
输出计划任务
set noexec on
不具体执行SQL

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值