我们再写sql的时候数据量大的话,会出现的一个问题,视图查一下,一秒不到,但是加了条件就需要花费十秒甚至更多的时间去查询
原因是触发了全表扫描
首先我们来看二个语句
SELECT [SCNAME],[TL_CheckTime] ,[SC] ,[SAMPLENO] ,[TL_Recipient] ,[TL_RecipientTime] ,[II_TL_YangpinBS] ,[II_TL_ChengZQJ] ,[II_TL_ChrequestID] ,[II_TL_JarID] ,[II_TL_BatchNum] ,[TESTER] ,[CHECKER] ,[PA_SHORT_DESC] ,[PANAME] ,[VALUE_S] ,[UNIT] ,[PASS] ,[KKVALUE] FROM [OpcenterRDnL].[RndSuite].[RndvRawMilkCansTOMES] where II_TL_ChrequestID in ( select ChrequestID from[dbo].[TB_InterfaceTestInformation] where RequestType =N'XXX' and IsReturn =0)
其中[SC]为主键,视图中的字段很多为子查询查出来的,请问现在这种情况,再视图无限大,in的字段再80条左右的情况下,如何能提升性能。
在这上面犯了二个错误
1.首先视图使用子查询会导致性能下降
2.触发了全表扫描,
虽然视图查起来很快,但是加了这个条件之后就慢了很多很多。首先第一个错误修改视图就能解决,第二个问题怎么解决呢,首先我们可以确定一点,全表扫描由于where条件导致的全表扫描,那么对于我们来说,如何把这个where处理成,不进行全表的扫描呢,那么我们就需要用到一个字段就是主键,原因在于主键不唯一,而且我们的主键是数字类型的,那么检索的速度将会极大的提升,上面的sql慢的原因就是,他的in的条件,是一个nvarchar200的字段所以他的检索效率就很慢了,那么我们就需要这个字段,但是我们不用他直接来进行关联该怎么办呢
第一步我们已经分析完了,第二步就开始实施,不用这个字段直接关联,首先我们要先认清一点,关联关系只有这个字段,那么关联的字段必定为string,如果为string必定少不了全表扫描。
第三步分析全表扫描
全表扫描的成本 = 表的数据块总数 / 多块读取
成本为2000行数据,每个数据有20列那么就有40000扫描成本。
据上述sql了解有19个字段,外加子查询那么就应该有19200020000会有8亿的数据级别,由此我们发现了什么这个数据是十分的庞大,按照2亿处理级别的数据库处理这个数据大约需要四秒,我们在实际的查询过程中大约是花了5秒左右
那么我们不用这个思路走换另一个方面使用主键索引起来找会有多少呢
SELECT [SCNAME],[TL_CheckTime],[SC] ,[RecipientTime] ,[SAMPLENO] ,[II_TL_ChrequestID] ,[II_TL_MilkcarName] ,[II_TL_BatchNum] ,[TESTER] ,[CHECKER] ,[PA_SHORT_DESC] ,[PANAME],[VALUE_S],[PASS] FROM[OpcenterRDnL].[RndSuite].[RndvZR99TOMES]where SC in ( Select b.SC from [RndSuite].[RndtRqIi]a join [RndSuite].[RndtRqSc]b on a.RQ = b.RQ where IIVALUE in (select ChrequestID from[dbo].[TB_InterfaceTestInformation] where RequestType = N'XXX' and IsReturn = 0) )
这个语句解决了一些问题,使用主键开启了索引,我们的SC字段是重复的2000条数只有200个SC,那么我们就会出现这个的成本12000/10 =200,后面的子查询的性能为11*20000那么in的话把2边的性能加起来一共是20200的性能使用2亿的处理只需要0.001秒就可以完成查询
测试可以的
总结
因为如果全表扫描外加几万条数据加子查询确实是可以达到亿级别的数据量,那么处理的办法最简单的方式不改子查询的话,使用索引就能解决。