SqlServer 执行计划及Sql查询优化初探
http://www.alixixi.com/program/a/2010062662233.shtml --建测试表 CREATE?TABLE?T_UserInfo ( Userid varchar(20),?UserName varchar(20), RegTime?datetime,?Tel varchar(20), ) --插入测试数据 DECLARE?@I?INT DECLARE?@ENDID?INT SELECT?@I?=?1 SELECT?@ENDID = 100?--在此处更改要插入的数据,重新插入之前要删掉所有数据 WHILE?@I?<=?@ENDID BEGIN INSERT?INTO?T_UserInfo SELECT?"ABCDE"+CAST(@I?AS?VARCHAR(20))+"EF","李"+CAST(@I?AS?VARCHAR(20)), GETDATE(),"876543"+CAST(@I?AS?VARCHAR(20)) SELECT?@I?=?@I?+?1 END --相关SQL语句解释 --------------------------------------------------------------------------- --建聚集索引 CREATE?CLUSTERED?INDEX?INDEX_Userid?ON?T_UserInfo?(Userid) --建非聚集索引 CREATE?NONCLUSTERED?INDEX?INDEX_Userid?ON?T_UserInfo?(Userid) --删除索引 DROP?INDEX?T_UserInfo.INDEX_Userid --------------------------------------------------------------------------- --------------------------------------------------------------------------- --显示有关由Transact-SQL?语句生成的磁盘活动量的信息 SET?STATISTICS?IO?ON --关闭有关由Transact-SQL?语句生成的磁盘活动量的信息 SET?STATISTICS?IO?OFF --显示[返回有关语句执行情况的详细信息,并估计语句对资源的需求] SET?SHOWPLAN_ALL?ON --关闭[返回有关语句执行情况的详细信息,并估计语句对资源的需求] SET?SHOWPLAN_ALL?OFF --------------------------------------------------------------------------- 请记住:SET?STATISTICS?IO?和?SET?SHOWPLAN_ALL?是互斥的。 OK,现在开始: 首先,我们插入100条数据 然后我写了一个查询语句: SELECT?*?FROM?T_UserInfo?WHERE?USERID="ABCDE6EF" 选中以上语句,按Ctrl+L,如下图 这就是MSSQL的执行计划:表扫描:扫描表中的行 然后我们来看该语句对IO的读写: 执行:SET?STATISTICS?IO?ON 此时再执行该SQL:SELECT?*?FROM?T_UserInfo?WHERE?USERID="ABCDE6EF" 切换到消失栏显示如下: 表"T_UserInfo"。扫描计数1,逻辑读1?次,物理读0?次,预读0?次。 解释下其意思: 四个值分别为: 执行的扫描次数; 从数据缓存读取的页数; 从磁盘读取的页数; 为进行查询而放入缓存的页数 重要:如果对于一个SQL查询有多种写法,那么这四个值中的逻辑读(logical reads)决定了哪个是最优化的。 接下来我们为其建一个聚集索引 执行CREATE?CLUSTERED?INDEX?INDEX_Userid?ON?T_UserInfo?(Userid) 然后再执行SELECT?*?FROM?T_UserInfo?WHERE?USERID="ABCDE6EF" 切换到消息栏如下显示: 表"T_UserInfo"。扫描计数1,逻辑读2?次,物理读0?次,预读0?次。 此时逻辑读由原来的1变成2, 说明我们又加了一个索引页,现在我们查询时,逻辑读就是要读两页(1索引页+1数据页),此时的效率还不如不建索引。 此时再选中查询语句,然后再Ctrl+L,如下图:
聚集索引查找:扫描聚集索引中特定范围的行 说明,此时用了索引。 OK,到这里你应该已经知道初步知道MSSQL查询计划和如何查看对IO的读取消耗了吧! 接下来我们继续: 现在我再把测试数据改变成1000条 再执行SET?STATISTICS?IO?ON,再执行 SELECT?*?FROM?T_UserInfo?WHERE?USERID="ABCDE6EF" 在不加聚集索引的情况下: 表"T_UserInfo"。扫描计数1,逻辑读7?次,物理读0?次,预读0?次。 在加聚集索引的情况下:CREATE?CLUSTERED?INDEX?INDEX_Userid?ON?T_UserInfo?(Userid) 表"T_UserInfo"。扫描计数1,逻辑读2?次,物理读0?次,预读0?次。 (其实也就是说此时是读了一个索引页,一个数据页) 如此,在数据量稍大时,索引的查询优势就显示出来了。 先小总结下: 当你构建SQL语句时,按Ctrl+L就可以看到语句是如何执行,是用索引扫描还是表扫描? 通过SET?STATISTICS?IO?ON?来查看逻辑读,完成同一功能的不同SQL语句,逻辑读 越小查询速度越快(当然不要找那个只有几百条记录的例子来反我)。 我们再继续深入: OK,现在我们再来看一次,我们换个SQL语句,来看下MSSQL如何来执行的此SQL呢? 现在去掉索引:DROP?INDEX?T_UserInfo.INDEX_Userid 现在打开[显示语句执行情况的详细信息]:SET?SHOWPLAN_ALL?ON 然后再执行:SELECT?*?FROM?T_UserInfo?WHERE?USERID?LIKE?"ABCDE8%" 看结果栏:结果中有些具体参数,比如IO的消耗,CPU的消耗。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |