扫二维码与项目经理沟通
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流
page=2'当前页
创新互联建站专注于灵宝企业网站建设,响应式网站设计,商城建设。灵宝网站建设公司,为灵宝等地区提供建站服务。全流程按需网站策划,专业设计,全程项目跟踪,创新互联建站专业和态度为您提供的服务
pagesize = 20'分页大小
IF page = 1 THEN
SQL = "select top " pagesize " * from YOURTABLE order by ID desc"
ELSE
SQL = "select top " pagesize " * from YOURTABLE where ID not in(select top "pagesize" ID from YOURTABLE where ext_area='欧美' and ext_type='动作' order by ID desc) and ext_area='欧美' and ext_type='动作' order by ID desc" 'where条件,里外都要加上
END IF
另外,团IDC网上有许多产品团购,便宜有口碑
在关系型数据库中使用索引能够提高数据库性能,这一点是非常明显的。用的索引越多,从数据库系统中得到数据的速度就越快。然而,需要注意的是,用的索引越多,向数据库系统中插入新数据所花费的时间就越多。在本文中,你将了解到微软的SQL Server数据库所支持的各种不同类型的索引,在这里你将了解到如何使用不同的方法来实现索引,通过这些不同的实现方法,你在数据库的读性能方面得到的远比在数据库的整体性能方面的损失要多得多。索引的定义索引是数据库的工具,通过使用索引,在数据库中获取数据的时候,就可以不用扫描数据库中的所有数据记录,这样能够提高系统获取数据的性能。使用索引可以改变数据的组织方式,使得所有的数据都是按照相似的结构来组织的,这样就可以很容易地实现数据的检索访问。索引是按照列来创建的,这样就可以根据索引列中的值来帮助数据库找到相应的数据。索引的类型微软的SQL Server 支持两种类型的索引:clustered 索引和nonclustered索引。Clustered 索引在数据表中按照物理顺序存储数据。因为在表中只有一个物理顺序,所以在每个表中只能有一个clustered索引。在查找某个范围内的数据时,Clustered索引是一种非常有效的索引,因为这些数据在存储的时候已经按照物理顺序排好序了。 Nonclustered索引不会影响到下面的物理存储,但是它是由数据行指针构成的。如果已经存在一个clustered索引,在nonclustered中的索引指针将包含clustered索引的位置参考。这些索引比数据更紧促,而且对这些索引的扫描速度比对实际的数据表扫描要快得多。 得到更好的性能 虽然索引可以带来性能上的优势,但是同时也将带来一定的代价。虽然SQL Server系统允许你在每个数据表中创建多达256个nonclustered索引,但是建议不要使用这么多的索引。因为索引需要在内存和物理磁盘驱动器上使用更多的存储空间。在执行插入声明的过程中可能会在一定程度上导致系统性能的下降,因为在插入数据的时候是需要根据索引的顺序插入,而不是在第一个可用的位置直接插入数据,这样一来,存在的索引越多将导致插入或者更新声明所需要的时间就越多。 在使用SQL Server系统创建索引的时候,建议参照下面的创建准则来实现: 正确的选择数据类型 在索引中使用某些数据类型可以提高数据库系统的效率,例如,Int,bigint, smallint,和tinyint等这些数据类型都非常适合于用在索引中,因为他们都占用相同大小的空间并且可以很容易地实现比较操作。其他的数据类型如char和varchar的效率都非常低,因为这些数据类型都不适合于执行数学操作,并且执行比较操作的时间都比上面提到数据类型要长。 确保在使用的过程中正确的利用索引值 在创建多列索引时,需要注意列的顺序 数据库将根据第一列索引的值来排列记录,然后进一步根据第二列的值来排序,依次排序直到最后一个索引排序完毕。哪一列唯一数据值较少,哪一列就应该为第一个索引,这样可以确保数据可以通过索引进一步交叉排序。 在clustered索引中限制列的数量 在clustered索引中用到的列越多,在nonclustered索引中包含的clustered索引参考位置就越多,需要存储的数据也就越多。这样将增加包含索引的数据表的大小,并且将增加基于索引的搜索时间。 避免频繁更新clustered索引数据列 由于nonclustered 索引依赖于clustered 索引,所以如果构成clustered 索引的数据列频繁更新,将导致在nonclustered中存储的行定位器也将随之频繁更新。对于所有与这些列相关的查询来说,如果发生记录被锁定的情况时,这将可能导致性能成本的增加。 分开操作(如果可能的话) 对于一个表来说,如果需要进行频繁的执行插入、更新操作,同时还有大量读操作的话,在可能的情况下尝试将这个表分开操作。所有的插入和更新操作可以在一个没有索引的表中操作,然后将其复制到另外一个表中,在这个表里有大量的索引可以优化读数据的能力。 适当的重建索引 Nonclustered索引包含clustered索引的指针,这样一来Nonclustered索引将从属于clustered 索引。当重建clustered索引时,首先是丢弃原来的索引,然后再使用CREATE INDEX 来创建索引,或者在使用CREATE INDEX 声明的同时将DROP_EXISTING 子句作为重建索引的一部分。将丢弃和创建分为几步将会导致多次重建nonclustered 索引,而不象使用DROP_EXISTING 子句那样,只重建一次nonclustered 索引。 明智的使用填充因子 数据存储在那些具有固定大小的连续内存页面内。随着新的记录行的加入,数据内存页将逐渐被填满,系统就必须执行数据页的拆分工作,通过这个拆分工作将部分数据转移到下一个新的页面当中。这样的拆分之后,将加重系统的负担,并且会导致存储的数据支离破碎。填充因子可以维护数据之间的缺口,一般在创建索引的时候,该索引的填充因子就已经被设置好了。这样一来,可以减少插入数据所引起的页面分裂的次数。因为只是在创建索引的时候才维护空间的大小,在增加数据或者更新数据时不会去维护空间的大小。因此,要想能够充分的利用填充因子,就必须周期性的重建索引。由填充因子所造成的缺口将导致读性能的下降,因为随着数据库的扩张,越来越多的磁盘存取工作需要读取数据。所以,在读的次数超过写的次数的时候,很重要的一点是考虑使用填充因子还是使用缺省方式合适。 管理层的决策 通过有效的使用索引,可以在微软的SQL Server系统中实现很好的查询功能,但是使用索引的效率取决于几种不同的实现决策。在索引的性能平衡方面,要做出正确的数据库管理决策意味着需要在良好的性能和困境中抉择。在特定的情况下,本文给出的一些建议将有助于你做出正确的决策。
分两步实现
一、分页的存储过程如下
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
CREATE PROCEDURE [dbo].[Pagination]
@tblName varchar(255), -- 表名
@strGetFields varchar(1000) , -- 需要返回的列
@fldName varchar(255), -- 排序的字段名
@PageSize int, -- 页尺寸
@PageIndex int , -- 页码
@doCount bit=0, -- 返回记录总数, 非 0 值则返回
@OrderType bit, -- 设置排序类型, 非 0 值则降序
@strWhere varchar(1500) -- 查询条件 (注意: 不要加 where)
AS
declare @strSQL varchar(5000) -- 主语句
declare @strTmp varchar(110) -- 临时变量
declare @strOrder varchar(400) -- 排序类型
if @doCount != 0
begin
if @strWhere !=''
set @strSQL = 'select count(*) as Total from [' + @tblName + '] where ' + @strWhere
else
set @strSQL = 'select count(*) as Total from [' + @tblName + ']'
end
--以上代码的意思是如果@doCount传递过来的不是0,就执行总数统计。以下的所有代码都是@doCount为0的情况
else
begin
if @OrderType != 0
begin
set @strTmp = '(select min'
set @strOrder = ' order by [' + @fldName + '] desc'
end
--如果@OrderType不是0,就执行降序,这句很重要!
else
begin
set @strTmp = '(select max'
set @strOrder = ' order by [' + @fldName + '] asc'
end
if @PageIndex = 1
begin
if @strWhere != ''
set @strSQL = 'select top ' + str(@PageSize) + ' ' + @strGetFields + ' from [' + @tblName + '] where '
+ @strWhere + ' ' + @strOrder
else
set @strSQL = 'select top ' + str(@PageSize) + ' ' + @strGetFields
+ ' from [' + @tblName + '] ' + @strOrder
end
--如果是第一页就执行以上代码,这样会加快执行速度
else
begin
--以下代码赋予了@strSQL以真正执行的SQL代码
set @strSQL = 'select top ' + str(@PageSize) + ' ' + @strGetFields + ' from ['
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['+ @fldName + ']) from (select top '
+ str( ( @PageIndex - 1 ) * @PageSize ) + ' ['+ @fldName + '] from [' + @tblName + ']'
+ @strOrder + ') as tblTmp)' + @strOrder
if @strWhere != ''
set @strSQL = 'select top ' + str(@PageSize) + ' ' + @strGetFields + ' from ['
+ @tblName + '] where [' + @fldName + ']' + @strTmp + '(['
+ @fldName + ']) from (select top ' + str( ( @PageIndex - 1 ) * @PageSize ) + ' ['
+ @fldName + '] from [' + @tblName + '] where ' + @strWhere + ' '
+ @strOrder + ') as tblTmp) and ' + @strWhere + ' ' + @strOrder
end
end
exec(@strSQL)
二、页面调用部分代码
Function navindex(ByVal PageIndextemp As Integer, ByVal PageSizetemp As Integer, ByVal countint As Integer, ByVal pagename As String) As String
Dim i As Integer
If countint Mod PageSizetemp = 0 Then
i = countint \ PageSizetemp
Else
i = countint \ PageSizetemp + 1
End If
Dim maxi, mini As Integer
Dim navleft, navright, navstrtemp As String
If i 10 Then
maxi = i
mini = 1
Else
maxi = pageindex + 3
mini = pageindex - 3
If mini 1 Then
navleft = "a href=""" pagename "?page=" (mini - 1) """ class=""link_nav_btn""/a "
Else
mini = 1
maxi = 10
End If
If maxi i Then
navright = " a href=""" pagename "?page=" (maxi + 1) """ class=""link_nav_btn""/a"
Else
If i - 10 0 Then
mini = i - 10
Else
mini = 1
End If
maxi = i
End If
End If
For n As Integer = mini To maxi
If n = pageindex Then
navstrtemp = navstrtemp " a href=""" pagename "?page=" n """ class=""link_nav_btn_select""b" n "/b/a"
Else
navstrtemp = navstrtemp " a href=""" pagename "?page=" n """ class=""link_nav_btn""" n "/a"
End If
Next
navstrtemp = navleft navstrtemp navright
Return navstrtemp
End Function
Sub databinds(ByVal tblnametemp As String, ByVal strGetFieldstemp As String, ByVal fldNametemp As String, ByVal PageSizetemp As Integer, ByVal PageIndextemp As Integer, ByVal OrderTypetemp As Short, ByVal strWheretemp As String)
'tblnametemp表名,strGetFieldstemp需要返回的列,fldNametemp排序的字段名,PageSizetemp页尺寸,PageIndextemp页码,OrderTypetemp设置排序类型,strWheretemp查询条件
'总数
cmdTM = New SqlCommand("select count(*) from " tblnametemp " where " strWheretemp, conPubs)
conPubs.Open()
countint = CInt(cmdTM.ExecuteScalar())
conPubs.Close()
'导航
navstr = navindex(PageIndextemp, PageSizetemp, countint, "newshyxh.aspx")
'分页
cmdTM = New SqlCommand("Pagination", conPubs)
cmdTM.CommandType = CommandType.StoredProcedure
'add input
cmdTM.Parameters.Add("@tblName", SqlDbType.VarChar, 255).Value = tblnametemp
cmdTM.Parameters.Add("@strGetFields", SqlDbType.VarChar, 1000).Value = strGetFieldstemp
cmdTM.Parameters.Add("@fldName", SqlDbType.VarChar, 255).Value = fldNametemp
cmdTM.Parameters.Add("@PageIndex", SqlDbType.Int).Value = PageIndextemp
cmdTM.Parameters.Add("@PageSize", SqlDbType.Int).Value = PageSizetemp
cmdTM.Parameters.Add("@OrderType", SqlDbType.Bit).Value = OrderTypetemp
cmdTM.Parameters.Add("@strWhere", SqlDbType.VarChar, 1500).Value = strWheretemp
conPubs.Open()
newsright.DataSource = cmdTM.ExecuteReader()
newsright.DataBind()
conPubs.Close()
End Sub
存储过程:create Procedure pname
( @pageIndex int,@pageSize)
as
select * from tableName order by id
offset @pageIndex * pageSize fetch next pageSize rows only
分页:
sqlserver 在2008之前 使用 top 和 not int top 的方式来做分页
2008以后使用 row_number() 函数作为分页关键函数
2012使用 offset 1 fetch next 10 rows only
你问了2个问题,你可以优先把视图,存储过程,触发器等弄明白,分页是查询,在存储过程里可以写复杂的sql文,只是在运行时是预编译和参数化查询防止sql注入
在良好的数据库设计基础上,能有效地使用索引是SQL Server取得高性能的基础,SQL Server采用基于代价的优化模型,它对每一个提交的有关表的查询,决定是否使用索引或用哪一个索引。因为查询执行的大部分开销是磁盘I/O,使用索引提高性能的一个主要目标是避免全表扫描,因为全表扫描需要从磁盘上读表的每一个数据页,如果有索引指向数据值,则查询只需读几次磁盘就可以了。
所以如果建立了合理的索引,优化器就能利用索引加速数据的查询过程。但是,索引并不总是提高系统的性能,在增、删、改操作中索引的存在会增加一定的工作量,因此,在适当的地方增加适当的索引并从不合理的地方删除次优的索引,将有助于优化那些性能较差的SQL Server应用。实践表明,合理的索引设计是建立在对各种查询的分析和预测上的,只有正确地使索引与程序结合起来,才能产生最佳的优化方案。本文就SQL Server索引的性能问题进行了一些分析和实践。
一、聚簇索引(clustered indexes)的使用
聚簇索引是一种对磁盘上实际数据重新组织以按指定的一个或多个列的值排序。由于聚簇索引的索引页面指针指向数据页面,所以使用聚簇索引查找数据几乎总是比使用非聚簇索引快。每张表只能建一个聚簇索引,并且建聚簇索引需要至少相当该表120%的附加空间,以存放该表的副本和索引中间页。建立聚簇索引的思想是:
1、大多数表都应该有聚簇索引或使用分区来降低对表尾页的竞争,在一个高事务的环境中,对最后一页的封锁严重影响系统的吞吐量。
2、在聚簇索引下,数据在物理上按顺序排在数据页上,重复值也排在一起,因而在那些包含范围检查(between、、=、、=)或使用group by或order by的查询时,一旦找到具有范围中第一个键值的行,具有后续索引值的行保证物理上毗连在一起而不必进一步搜索,避免了大范围扫描,可以大大提高查询速度。
3、在一个频繁发生插入操作的表上建立聚簇索引时,不要建在具有单调上升值的列(如IDENTITY)上,否则会经常引起封锁冲突。
4、在聚簇索引中不要包含经常修改的列,因为码值修改后,数据行必须移动到新的位置。
5、选择聚簇索引应基于where子句和连接操作的类型。
聚簇索引的侯选列是:
1、主键列,该列在where子句中使用并且插入是随机的。
2、按范围存取的列,如pri_order 100 and pri_order 200。
3、在group by或order by中使用的列。
4、不经常修改的列。
5、在连接操作中使用的列。
二、非聚簇索引(nonclustered indexes)的使用
SQL Server缺省情况下建立的索引是非聚簇索引,由于非聚簇索引不重新组织表中的数据,而是对每一行存储索引列值并用一个指针指向数据所在的页面。换句话说非聚簇索引具有在索引结构和数据本身之间的一个额外级。一个表如果没有聚簇索引时,可有250个非聚簇索引。每个非聚簇索引提供访问数据的不同排序顺序。在建立非聚簇索引时,要权衡索引对查询速度的加快与降低修改速度之间的利弊。另外,还要考虑这些问题:
1、索引需要使用多少空间。
2、合适的列是否稳定。
3、索引键是如何选择的,扫描效果是否更佳。
4、是否有许多重复值。
对更新频繁的表来说,表上的非聚簇索引比聚簇索引和根本没有索引需要更多的额外开销。对移到新页的每一行而言,指向该数据的每个非聚簇索引的页级行也必须更新,有时可能还需要索引页的分理。从一个页面删除数据的进程也会有类似的开销,另外,删除进程还必须把数据移到页面上部,以保证数据的连续性。所以,建立非聚簇索引要非常慎重。非聚簇索引常被用在以下情况:
1、某列常用于集合函数(如Sum,....)。
2、某列常用于join,order by,group by。
3、查寻出的数据不超过表中数据量的20%。
三、覆盖索引(covering indexes)的使用
覆盖索引是指那些索引项中包含查寻所需要的全部信息的非聚簇索引,这种索引之所以比较快也正是因为索引页中包含了查寻所必须的数据,不需去访问数据页。如果非聚簇索引中包含结果数据,那么它的查询速度将快于聚簇索引。
但是由于覆盖索引的索引项比较多,要占用比较大的空间。而且update操作会引起索引值改变。所以如果潜在的覆盖查询并不常用或不太关键,则覆盖索引的增加反而会降低性能。
四、索引的选择技术
p_detail是住房公积金管理系统中记录个人明细的表,有890000行,观察在不同索引下的查询运行效果,测试在C/S环境下进行,客户机是IBM PII350(内存64M),服务器是DEC Alpha1000A(内存128M),数据库为SYBASE11.0.3。
1、 select count(*) from p_detail where
op_date’19990101’ and op_date’
19991231’ and pri_surplus1300
2、 select count(*),sum(pri_surplus1) from p_detail
where op_date’19990101’ and
pay_month between‘199908’ and’199912’
不建任何索引查询1 1分15秒
查询2 1分7秒
在op_date上建非聚簇索引查询1 57秒
查询2 57秒
在op_date上建聚簇索引查询1 1秒
查询2 52秒
在pay_month、op_date、pri_surplus1上建索引查询1 34秒
查询2 1秒
在op_date、pay_month、pri_surplus1上建索引查询1 1秒
查询2 1秒
从以上查询效果分析,索引的有无,建立方式的不同将会导致不同的查询效果,选择什么样的索引基于用户对数据的查询条件,这些条件体现于where从句和join表达式中。一般来说建立索引的思路是:
(1)主键时常作为where子句的条件,应在表的主键列上建立聚簇索引,尤其当经常用它作为连接的时候。
(2)有大量重复值且经常有范围查询和排序、分组发生的列,或者非常频繁地被访问的列,可考虑建立聚簇索引。
(3)经常同时存取多列,且每列都含有重复值可考虑建立复合索引来覆盖一个或一组查询,并把查询引用最频繁的列作为前导列,如果可能尽量使关键查询形成覆盖查询。
(4)如果知道索引键的所有值都是唯一的,那么确保把索引定义成唯一索引。
(5)在一个经常做插入操作的表上建索引时,使用fillfactor(填充因子)来减少页分裂,同时提高并发度降低死锁的发生。如果在只读表上建索引,则可以把fillfactor置为100。
(6)在选择索引键时,设法选择那些采用小数据类型的列作为键以使每个索引页能够容纳尽可能多的索引键和指针,通过这种方式,可使一个查询必须遍历的索引页面降到最小。此外,尽可能地使用整数为键值,因为它能够提供比任何数据类型都快的访问速度。
五、索引的维护
上面讲到,某些不合适的索引影响到SQL Server的性能,随着应用系统的运行,数据不断地发生变化,当数据变化达到某一个程度时将会影响到索引的使用。这时需要用户自己来维护索引。索引的维护包括:
1、重建索引
随着数据行的插入、删除和数据页的分裂,有些索引页可能只包含几页数据,另外应用在执行大块I/O的时候,重建非聚簇索引可以降低分片,维护大块I/O的效率。重建索引实际上是重新组织B-树空间。在下面情况下需要重建索引:
(1)数据和使用模式大幅度变化。
(2)排序的顺序发生改变。
(3)要进行大量插入操作或已经完成。
(4)使用大块I/O的查询的磁盘读次数比预料的要多。
(5)由于大量数据修改,使得数据页和索引页没有充分使用而导致空间的使用超出估算。
(6)dbcc检查出索引有问题。
当重建聚簇索引时,这张表的所有非聚簇索引将被重建。
2、索引统计信息的更新
当在一个包含数据的表上创建索引的时候,SQL Server会创建分布数据页来存放有关索引的两种统计信息:分布表和密度表。优化器利用这个页来判断该索引对某个特定查询是否有用。但这个统计信息并不动态地重新计算。这意味着,当表的数据改变之后,统计信息有可能是过时的,从而影响优化器追求最有工作的目标。因此,在下面情况下应该运行update statistics命令:
(1)数据行的插入和删除修改了数据的分布。
(2)对用truncate table删除数据的表上增加数据行。
(3)修改索引列的值。
六、结束语
实践表明,不恰当的索引不但于事无补,反而会降低系统的执行性能。因为大量的索引在插入、修改和删除操作时比没有索引花费更多的系统时间。例如下面情况下建立的索引是不恰当的:
1、在查询中很少或从不引用的列不会受益于索引,因为索引很少或从来不必搜索基于这些列的行。
2、只有两个或三个值的列,如男性和女性(是或否),从不会从索引中得到好处。
另外,鉴于索引加快了查询速度,但减慢了数据更新速度的特点。可通过在一个段上建表,而在另一个段上建其非聚簇索引,而这两段分别在单独的物理设备上来改善操作性能。
我们在微信上24小时期待你的声音
解答本文疑问/技术咨询/运营咨询/技术建议/互联网交流