某天上午,领导突然说,这服务器怎么时好时坏,cpu经常占用100%。我也没多想到底是怎么回事,心想重启能解决问题吧,可是重启没多久,cpu又飙到了100%,还是间隔出现的。于是打开数据库查询了一下当前正在执行哪些操作。发现里面一个session的cpu列值变化的比较快,dm_os_wait_stats表里面 CXPACKET等待类型的占用的时间比较多,通过查询 dm_exec_requests视图
发现是select语句,相应的存储过程是:
ALTER PROCEDURE [dbo].[Proc_Get_LonLat]
(
@cell int,
@lac int,
@mnc int
)
AS
begin
select
LNG,LAT,O_LNG,O_LAT,PRECISION,ADDRESS
FROM dbo.cellid
WHERE CELL = @cell and LAC = @lac and MNC = @mnc
end
逻辑很简单,就根据传入的条件查询相应的数据。
手动调用存储过程执行一次,发现里面的执行计划用到了并行查询操作Repartition Streams,执行计划也是index scan
查看表cellid的这3列的类型,cell、lac、mnc都是nvarchar(50),这3列上建了组合索引,有索引怎么不走index seek,而是选择了index scan?还用到了并行执行?
随即查询了一下CXPACKET 等待类型的含义:
当为SQL查询创建一个并行操作时,会有多个线程去执行这个查询。每个查询处理不同的数据集或行集。 因为某些原因,一个或多个线程滞后,而产生了CXPACKET等待状态。有一个组织/协调(organizer/coordinator)线程(Thread 0),它需要等待所有线程完成并聚合数据来呈现给客户端。组织线程必须等待所有线程完成处理才能进行下一步。由于组织线程等待缓慢的线程完成处理所产生的等待,就叫CXPACKET等待。
大致意思就是sql优化器认为本次查询的数据比较多,就采取了并行操作,用多个线程去执行这个查询。每个查询处理不同的数据集或行集,加快数据的处理。本身这个表的数据量好像在3,4百万左右,按这种写法等到查询结果出来需要10多秒的时间,想来出现这个cxpacket等待也应该是对的。但是查询为什么没用上索引查找呢?怀疑是字段的类型跟传入的类型不一致,于是改了下sql的写法,显示地转换了数据类型,并行度操作消失,并且执行计划用的index seek,问题解决
select LNG,LAT,O_LNG,O_LAT,PRECISION,ADDRESS
FROM dbo.cellid WHERE CELL = cast(@cell as nvarchar(50))
and LAC = cast(@lac as nvarchar(50))
and MNC = cast(@mnc as nvarchar(50))
结论:外部传入的数据类型需和字段的类型一致才能用上正确的索引。
本文暂时没有评论,来添加一个吧(●'◡'●)