SQL简单select奇怪问题
A.declare @s varchar(20),@i int
set @s='1001001'
select @i=病人ID from 住院病人登记记录 where 住院号=@s
select * from 住院病人费用明细记录 where 病人ID=@i
B.declare @s varchar(20)
set @s='1001001'
select * from 住院病人费用明细记录 where 病人ID=
(select 病人ID from 住院病人登记记录 where 住院号=@s)
这两条语句功能完全一样,返回结果也完全一样,但执行时间相差很远
A:
表 'Pub_Departments'。扫描计数 3,逻辑读 4 次,物理读 0 次,预读 0 次。
表 'Inpt_Registers'。扫描计数 1,逻辑读 5 次,物理读 0 次,预读 0 次。
表 'Inpt_Patients'。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。
SQL Server 执行时间:
CPU 时间 = 0 毫秒,耗费时间 = 0 毫秒。
(所影响的行数为 293 行)
表 'Pub_Tariff'。扫描计数 221,逻辑读 476 次,物理读 0 次,预读 0 次。
表 'Inpt_Wastebook'。扫描计数 2,逻辑读 4 次,物理读 0 次,预读 0 次。
表 'Pub_Medicines'。扫描计数 72,逻辑读 174 次,物理读 0 次,预读 0 次。
表 'Inpt_SpecializedTrpMaster'。扫描计数 62,逻辑读 143 次,物理读 0 次,预读 0 次。
表 'Inpt_SpecializedTrpDetail'。扫描计数 2,逻辑读 426 次,物理读 0 次,预读 0 次。
表 'Inpt_TranCtnOrderMaster'。扫描计数 2,逻辑读 892 次,物理读 0 次,预读 0 次。
表 'Inpt_CtnOrderMaster'。扫描计数 273,逻辑读 897 次,物理读 0 次,预读 0 次。
表 'Inpt_CtnOrderDetail'。扫描计数 0,逻辑读 0 次,物理读 0 次,预读 0 次。
表 'Inpt_TranCtnOrderDetail'。扫描计数 2,逻辑读 4 次,物理读 0 次,预读 0 次。
表 'Pub_Departments'。扫描计数 95,逻辑读 190 次,物理读 0 次,预读 0 次。
表 'Inpt_OrderMaster'。扫描计数 3,逻辑读 636 次,物理读 0 次,预读 0 次。
表 'Inpt_OrderDetail'。扫描计数 2,逻辑读 2 次,物理读 0 次,预读 0 次。
SQL Server 执行时间:
CPU 时间 = 31 毫秒,耗费时间 = 64 毫秒。
B:
(所影响的行数为 293 行)
表 'Pub_Tariff'。扫描计数 2341,逻辑读 5265 次,物理读 0 次,预读 0 次。
表 'Inpt_Wastebook'。扫描计数 2,逻辑读 466 次,物理读 0 次,预读 0 次。
表 'Pub_Medicines'。扫描计数 617,逻辑读 1631 次,物理读 0 次,预读 0 次。
表 'Inpt_SpecializedTrpDetail'。扫描计数 2,逻辑读 42952 次,物理读 0 次,预读 0 次。
表 'Inpt_SpecializedTrpMaster'。扫描计数 2,逻辑读 1086 次,物理读 0 次,预读 0 次。
表 'Inpt_TranCtnOrderMaster'。扫描计数 922,逻辑读 133898 次,物理读 0 次,预读 0 次。
表 'Inpt_TranCtnOrderDetail'。扫描计数 1,逻辑读 77 次,物理读 0 次,预读 0 次。
表 'Inpt_CtnOrderMaster'。扫描计数 244,逻辑读 31161 次,物理读 0 次,预读 0 次。
表 'Inpt_CtnOrderDetail'。扫描计数 2,逻辑读 15 次,物理读 0 次,预读 0 次。
表 'Pub_Departments'。扫描计数 6,逻辑读 10 次,物理读 0 次,预读 0 次。
表 'Inpt_OrderMaster'。扫描计数 12,逻辑读 120337 次,物理读 0 次,预读 0 次。
表 'Inpt_OrderDetail'。扫描计数 2,逻辑读 20 次,物理读 0 次,预读 0 次。
表 'Inpt_Registers'。扫描计数 1,逻辑读 5 次,物理读 0 次,预读 0 次。
表 'Inpt_Patients'。扫描计数 1,逻辑读 2 次,物理读 0 次,预读 0 次。
SQL Server 执行时间:
CPU 时间 = 7140 毫秒,耗费时间 = 16608 毫秒。
百思不得其解,有SQL高手指点一下吗?
------解决方案-------------------- 分别选中这两句SQL,按CTRL + L看看执行计划或许你就清楚了。
------解决方案-------------------- 子查询
------解决方案-------------------- 因为in 子查询,是返回 一个结果集,每次都返回一个结果集,反复查询,资源消耗大。
而第一个只返回一个值,只查询一次。
改成下面,还更快
SQL code
declare @s varchar(20)
set @s='1001001'
select * from 住院病人费用明细记录 where
exists( select 病人ID from 住院病人登记记录 where 住院病人费用明细记录.病人ID=住院病人登记记录.病人ID and 住院号=@s)
------解决方案-------------------- 探讨 因为in 子查询,是返回 一个结果集,每次都返回一个结果集,反复查询,资源消耗大。 而第一个只返回一个值,只查询一次。 改成下面,还更快 SQL code declare @s varchar(20) set @s='1001001' select * from 住院病人费用明细记录 where exists( select 病人ID from 住院病人登记记录 whe……
------解决方案-------------------- B.declare @s varchar(20) set @s='1001001' select * from 住院病人费用明细记录 where 病人ID= (select 病人ID from 住院病人登记记录 where 住院号=@s) ================= 将“住院病人登记记录”中的“ 病人ID”加上index就可以了,你肯定执行了table scan,所以很慢。 程序中处理,你不可能像A那样分两次去DB取值,这样更消耗资源。