大家好,又见面了,我是你们的朋友全栈君。
一、视图的内部排序问
在 SQL Server里是不建议对视图进行排序的,下面是一位SQL Server专家的话:
Don’t put ORDER BY Statements in Views.
Delay sorting until you’re actually about to use the data.
If you end up sorting differently than the default sort specified by the ORDER BY in the view, it comes as an expensive performance hit. Witness a stored procedure that was breaking a unit test due to a SqlClient.SqlTimeout Exception (took 2.5 minutes to run). Removing the ORDER BY statements from the underlying views brought execution time down to 6 seconds.
简单的翻译如下:
不要在视图里面使用ORDER BY 语句,把排序延迟到你实际需要使用数据的时候。
对此,《Microsoft SQL Server 2005 技术内幕:T-SQL 程序设计》 一书对此进行了详细阐述,可见:http://book.csdn.net/bookfiles/441/10044115644.shtml
SQL Server 2005联机丛书有一段对该行为的描述:“在视图、内联函数、派生表或子查询的定义中使用 ORDER BY 时,子句只用于确定 TOP 子句返回的行。ORDER BY 不保证在查询这些构造时得到有序结果,除非在查询本身中也指定了 ORDER BY。”
我们如果查看该视图的执行计划,会发现根本就没有SORT的步骤发生。
如果确实需要使用视图排序的话,会有另外的一个选择,那就是使用“索引视图”,又叫物化视图,索引视图的定义很简单:对视图创建需 要的聚集索引 。但对视图创建聚集索引后,视图就不再是简单的查询语句了,而是类似于实际的表,该视图会存储相关的数据。这非常适用于在 使用频繁,而基表更新不频繁的情况,但如果基表更新频繁的话,维护额外的索引视图会是一个非常昂贵的代价。
创建索引视图时,需要将视图与基表绑定,也就是说,不能随便更改基表的定义,因为有视图依赖于该表。创建索引视图需要使用WITH SCHEMABINDING 选项。
二、聚集索引的一些原理介绍
在第一次碰到这个排序问题时,曾经通过使用更新索引上的统计信息来获取正确结果。可见如下的实验过程:
这是产生问题的SQL 语句:
Select * From V_L_IcStockProInEntry Where FInterID= ‘329482’
因为FINTERID,FSEQ对应于ICSTOCKPROINENTRY上有相应的聚集索引,而该表的插入十分频繁,相关信息未及时更新而导致了 排序混乱。
通过dbcc show_statistics(‘IcStockProInEntry’,PK_IcStockProInEntry)语句查看相关的统计信息
RANGE_HI_KEY RANGE_ROWS EQ_ROWS DISTINCT_RANGE_ROWS AVG_RANGE_ROWS
3 0 1 0 1…
….282987 101155 6 27942 3.620178
288803 18440 1 5253 3.510375
296886 24587 6 7468 3.292314
303529 18433 19 5799 3.178652
329478 71674 6 23077 3.105863
329480 0 4 0 1上述内容是pk_IcStockProInEntry的柱状图,可以看到 RANGE_HI_KEY并没有包含329482,也就是说改条记录只在逻辑上保持排序,而在物理上还是未进行排序的。
通过 UPDATE STATISTICS IcStockProInEntry pk_ IcStockProInEntry with full scan 或者ALTER INDEX PK_IcStockProInEntry ON IcStockProInEntry REBUILD 重建索引就可以保证排序的正确。
对于SQL Server来说,存在着聚集索引和非聚集索引两类索引,这两类索引的结构都是b-tree结构,但聚集索引不仅包括索引的key值,还包括了整个表的数 据。
当对表上的列建立索引后,会对其进行排序,排序又分逻辑排序和物理排序。
逻辑排序是指保证该列上的数据按某种顺序进行排序,获取某条数据时,能正确获取下一条数据;
物理排序则是指SQL Server在索引页上通过指针来保证相关的数据页按照一定的顺序存放。
其实,从这里也可以看出,SQL Server并不能百分百的保证获取的数据会是正确的顺序,创建索引时,也只是保证了逻辑排序,而无法保证物理排序。如果某个表上有着频繁的更新,当某个 page无法装载更新后的内容时,SQL Srever会将相关的内容移动到另外一个page上去,而在原page上只保存着指针,这个动作叫“split”,中文为”分裂“,当索引页发生分裂 时,也是索引碎片产生的时候了,这时,索引页的物理排序就不是原来的顺序了。通过dbcc showcontig可以查看一个表或者索引的碎片程度,碎片多的情况下,获取数据会得有额外的消耗,进而引起性能下降。通过索引重建能让物理排序让逻辑 排序重新匹配,消除碎片。
三、总结
排序是一个十分耗费性能的操作,一般进行排序时,都是通过指定where条件来限制结果集后,再使用ORDER BY语句进行排序。SQL Server并不会事先对数据进行很好排序,要获得正确的排序结果,只能通过指定ORDER BY 。
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/163039.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...