??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲AV无码成人精品区狼人影院 ,亚洲精品一二三区,亚洲精品无码久久久久http://www.tkk7.com/wuxufeng8080/category/10539.html弱水三千Q只取一瓢,便能解Q佛法无边,奉行一法,便能得益?/description>zh-cnSun, 29 Jul 2012 00:05:06 GMTSun, 29 Jul 2012 00:05:06 GMT60查询数据库中表的数据行数http://www.tkk7.com/wuxufeng8080/articles/383527.html风h?/dc:creator>风h?/author>Thu, 19 Jul 2012 10:10:00 GMThttp://www.tkk7.com/wuxufeng8080/articles/383527.htmlhttp://www.tkk7.com/wuxufeng8080/comments/383527.htmlhttp://www.tkk7.com/wuxufeng8080/articles/383527.html#Feedback0http://www.tkk7.com/wuxufeng8080/comments/commentRss/383527.htmlhttp://www.tkk7.com/wuxufeng8080/services/trackbacks/383527.html
create proc ss
as
set nocount on
create table TableSpace
(
TableName varchar(50),
RowsCount char(11),
Reserved varchar(18),
Data varchar(18),
Index_size varchar(18),
Unused varchar(18) 
)
declare @sql varchar(500)
declare @TableName varchar(50)
declare Cursor1 Cursor
for 
select name from sysobjects where xtype='U'
open Cursor1
fetch next from Cursor1 into @TableName
while @@fetch_status = 0
begin
set @sql = 'insert into TableSpace '
set @sql = @sql + ' exec sp_spaceused '''+ @TableName + ''' '
exec (@sql)
fetch next from Cursor1 into @TableName
end
close Cursor1
deallocate Cursor1
select tableName,rowscount from TableSpace where tableName<>'TableSpace'
order by rowscount desc
drop table TableSpace
go
exec ss


]]>
sql server2000数据分页的两U方?/title><link>http://www.tkk7.com/wuxufeng8080/articles/279502.html</link><dc:creator>风h?/dc:creator><author>风h?/author><pubDate>Tue, 02 Jun 2009 00:30:00 GMT</pubDate><guid>http://www.tkk7.com/wuxufeng8080/articles/279502.html</guid><wfw:comment>http://www.tkk7.com/wuxufeng8080/comments/279502.html</wfw:comment><comments>http://www.tkk7.com/wuxufeng8080/articles/279502.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/wuxufeng8080/comments/commentRss/279502.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/wuxufeng8080/services/trackbacks/279502.html</trackback:ping><description><![CDATA[如果一个查询的l果数据量巨大,需要数据查询的时候就分页Q每ơ只q回其中一?br /> <br /> <strong>W一U方法:</strong><br /> 思\是根据页号取Z部分数据Q比如取出前90条,然后取出?00条,然后比较取出两次l果的差集?br /> <br /> ?0万条记录的情况下Q如果只?00(l果?0000条记录)Q大U需?分半钟。烦引徏得好的话Q?分钟左右?br /> <br /> <br /> //select * from //q一句是不能修改的了Q因为它是从l果中读取,所以必要?<br /> //(select top @h_count (@filedlist) from @tableName .....) as big //取出W合条g的上限的记录<br /> //where <br /> //big.guid   //q里是关键,Ҏ主键从下限结果中qo掉重复的记录Q只留下不同的数据,也就是求交集Q?br /> //not in <br /> //(select top @l_count guid from @table .....)//下限<br /> //order @orderby  //原来的格式,q里只保留了orderby之后的,应该保留条g之后所有的Q包括gruopby什么的<br /> <br /> 函数cM如此Q?br />   public string MakeSqlPager(string sourceSql,int pageIndex)<br />   {<br />    //使用默认面大小<br />    string orderbyStr=sourceSql.Substring(sourceSql.ToLower().IndexOf("order by"));<br />    int index=sourceSql.ToLower().IndexOf("select");<br />    string bigRes="("+ sourceSql.Insert(index+6," top "+((pageIndex+1)*_pageSize).ToString()+" ")+") as big";<br />    string smallRes="("+ sourceSql.Insert(index+6," top "+(pageIndex*_pageSize).ToString()+" ")+")";<br />    return "select * from "+bigRes+" where big.guid not in "+smallRes+" "+orderbyStr;<br />   }<br /> <br /> q种Ҏq可以改q,是W二ơ取qo时从W一个的l果里面qo?br /> <br /> <strong>W二U方法:</strong><br /> 掐头dQ程序还没写<br /> SELECT * FROM<br /> (<br />   SELECT TOP 100 * FROM<br />   (<br />     SELECT TOP 100000 * FROM pagetest ORDER BY regt ASC<br />    ) as a<br />   ORDER BY regt desc<br /> ) as b<br />  ORDER BY regt ASC<br /> <br /> 试了一下,大约用时?9U?br /> <br /> <strong>比较Q?br /> </strong>W一U方法的效率很低Q猜是因ؓ多次需要@环比较,旉复杂度要高一个等U。比如,q种Ҏ的响应时间和所取得的页h很大关系?br /> W二U方法还是可以接受的Q和号无关Q但是也需要两ơ比?br /> <br /> |上q有使用比较ID的方法的Q但是不是所有的表都有IDQ即使有Q也不一定是intcd的?br /> q有用存储过E创Z时表的,我还没有试效率如何<br /> <br /> sqlserver里面没有rownum q个功能Q最新的2005beta2版本据说有了QOracle里面有)Q所以一ơ比较就能分늚法q真不好? <img src ="http://www.tkk7.com/wuxufeng8080/aggbug/279502.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/wuxufeng8080/" target="_blank">风h?/a> 2009-06-02 08:30 <a href="http://www.tkk7.com/wuxufeng8080/articles/279502.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL SERVER定时备䆾数据?/title><link>http://www.tkk7.com/wuxufeng8080/articles/213835.html</link><dc:creator>风h?/dc:creator><author>风h?/author><pubDate>Wed, 09 Jul 2008 23:39:00 GMT</pubDate><guid>http://www.tkk7.com/wuxufeng8080/articles/213835.html</guid><wfw:comment>http://www.tkk7.com/wuxufeng8080/comments/213835.html</wfw:comment><comments>http://www.tkk7.com/wuxufeng8080/articles/213835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/wuxufeng8080/comments/commentRss/213835.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/wuxufeng8080/services/trackbacks/213835.html</trackback:ping><description><![CDATA[<p align="left"><span>点击<span> "</span>理<span>"--"sql server</span>代理<span>"--"</span>作业<span>"</span></span></p> <p align="left"><span>新徏作业Q?/span></p> <p align="left"><span>常规选项卡里<span>,"</span>名称<span>"</span>填写<span>"</span>定时备䆾数据?span>"</span>Q?span>"</span>启用<span>"</span>前面?span>"</span>对勾<span>"</span>Q?span>"</span>以本地服务器为目?span>"</span>Q?/span></p> <p align="left"><span> "</span><span>分类<span>"</span>选择<span>"</span>数据库服?span>"</span>Q?/span></p> <p align="left"><span>步骤选项卡里Q新建步骤,步骤名:备䆾数据库;cdQ?span>Transact-SQL</span>脚本<span>(TSQL);</span></span></p> <p align="left"><span> </span><span>数据库:要备份的数据库;</span></p> <p align="left"><span> </span><span>命oQ?span> </span></span></p> <p align="left"><span>declare @filename varchar (1000)</span></p> <p align="left"><span>set @filename='E:\</span><span>数据库备?span>\book'+convert(char(10),getdate(),112)</span></span></p> <p align="left"><span>print @filename</span></p> <p align="left"><span>BACKUP DATABASE [book] TO DISK = @filename WITH NOINIT , NOUNLOAD , NAME = N'</span><span>备䆾<span>', NOSKIP , STATS = 10, </span></span></p> <p align="left"><span>NOFORMAT </span></p> <p align="left"><span>调度选项卡里Q新度,名称<span>:</span>定时备䆾数据?span>; </span>调度cd<span>:</span>反复出现Q?/span></p> <p><span>通知选项卡里Q写?span>windows</span>应用E序事g日至。当作业p|时?/span></p> <img src ="http://www.tkk7.com/wuxufeng8080/aggbug/213835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/wuxufeng8080/" target="_blank">风h?/a> 2008-07-10 07:39 <a href="http://www.tkk7.com/wuxufeng8080/articles/213835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL Server 2005新增功能--Pivot & UnPivothttp://www.tkk7.com/wuxufeng8080/articles/110072.html风h?/dc:creator>风h?/author>Thu, 12 Apr 2007 01:33:00 GMThttp://www.tkk7.com/wuxufeng8080/articles/110072.htmlhttp://www.tkk7.com/wuxufeng8080/comments/110072.htmlhttp://www.tkk7.com/wuxufeng8080/articles/110072.html#Feedback0http://www.tkk7.com/wuxufeng8080/comments/commentRss/110072.htmlhttp://www.tkk7.com/wuxufeng8080/services/trackbacks/110072.html如下CZ
SELECT DATE, A.G, A.I, A.V, A.O, A.SC, A.LR, A.PR, A.HL FROM 
(
    
select date,PNLID, judge FROM dbo.RCI_LOI2MOVEMENT
)B
PIVOT (
COUNT(PNLID) FOR judge IN
(G, I, V, O, SC, LR, PR, HL )) A
WHERE DATE >= '2007-4-5' AND DATE <= '2007-4-11'
自动会以date作ؓGROUP BY 的栏?

]]>
SQL Server 2005新增功能--Row_NUMBER() 分页查询http://www.tkk7.com/wuxufeng8080/articles/110050.html风h?/dc:creator>风h?/author>Thu, 12 Apr 2007 00:43:00 GMThttp://www.tkk7.com/wuxufeng8080/articles/110050.htmlhttp://www.tkk7.com/wuxufeng8080/comments/110050.htmlhttp://www.tkk7.com/wuxufeng8080/articles/110050.html#Feedback0http://www.tkk7.com/wuxufeng8080/comments/commentRss/110050.htmlhttp://www.tkk7.com/wuxufeng8080/services/trackbacks/110050.html
SELECT * FROM
(
 
SELECT ROW_NUMBER() OVER(ORDER BY DATE) ROWNUM, * FROM BAS_CALENDAR
) CAL
WHERE ROWNUM BETWEEN (50*1)+1 AND 50*2
ORDER BY DATE ASC

开发圣l上的示例代?br>
CREATE PROC spGetPages2 @iRowCount INT@iRowPageNo INT
AS
SELECT * FROM (
SELECT ROW_NUMBER() OVER(ORDER BY ProductID ASC) RowNum, * FROM Production.Product ) OrderData
WHERE RowNum BETWEEN @iRowCount*(@iPageNo-1)+1 and @iRowCount*@iPageNo
ORDER BY ProductID ASC

GO

EXEC spGetPages2 10,20


]]>
最优化的ms sql server分页sql语句(ZT)http://www.tkk7.com/wuxufeng8080/articles/104651.html风h?/dc:creator>风h?/author>Mon, 19 Mar 2007 01:25:00 GMThttp://www.tkk7.com/wuxufeng8080/articles/104651.html说明Q?

pagesizeQ?每页昄记录?br />cureentpageQ当前页?/p>

select * from (  select TOP pagesize * FROM ( SELECT TOP pagesize*cureentpage  * from user_table  ORDER BY id ASC ) as aSysTable  ORDER BY id DESC ) as bSysTable  ORDER BY id ASC


例子说明Q?/p>

假如数据库表如下Q?/p>

user_table:

id:主键Q自?br />username:字符
password:字符

假设?0条记录,每页昄10条记录,id ??0


现在按照id升序排列取出W三늚数据应该为:所取得记录的id 应该?21?0?/p>

q时该语句应该ؓQ?/p>

select * from (  select TOP 10 * FROM ( SELECT TOP 30  * from user_table  ORDER BY id ASC ) as aSysTable  ORDER BY id DESC ) as bSysTable  ORDER BY id ASC

原理如下Q?/p>

先按照id从小到大升序取出30条记录(3*10Q?也就是:id ?1-30 之间的记?QSELECT TOP 30  * from user_table  ORDER BY id ASCQ?/p>

然后按照ID降序排列q?0条记录,得到记录为id 在:?0?1 

然后在这?0条记录中取出?0条记录:取得的记录ؓQid ?0-21之间。这是我们需要的数据Q但q时是按照降序排列的Q不W合要求?/p>

最后在重新排序得到最l我们需要的数据。id?1-30之间?/p>

]]>
Paging (MS SQL Server/Oracle)http://www.tkk7.com/wuxufeng8080/articles/99471.html风h?/dc:creator>风h?/author>Mon, 12 Feb 2007 07:57:00 GMThttp://www.tkk7.com/wuxufeng8080/articles/99471.html虽然 DataGrid 控g自己带了一个分处理机Ӟ但它是将W合查询条g的所有记录读入内存,然后q行分页昄的。随着W合条g的记录数目增多,׃出现q行效率问题Q或者至是资源的利用率下降?/p>

下面的代码示例都以下面的表结构ؓ准:

 

  Articles ?/td> SQL Server cd Oracle cd
PK Id int (自增) number(9) (插入时在当前最大g?)
  Author nvarchar(10) nvarchar2(10)
  Title nvarchar(50) nvarchar2(50)
  PubTime datetime date

SQL Server / Access {微软品中Q我们通常的自定义分页有两U思\Q?/p>

一U是?ASP.NET Forum Z表的、“时表”方法:卛_存储q程中徏立一个时表Q该临时表包含一个序号字D(1Q?Q?Q?...Q以及表的主键(其他能够唯一定一行记录的字段也是可以的)字段。存储过E可能如下:Q编?SS1Q?/font>

CREATE Procedure GetAllArticles_Paged
(
     @PageIndex int,
     @PageSize int,
     @TotalRecords out int,
     @TotalPages out int
)
AS

DECLARE @PageLowerBound int
DECLARE @PageUpperBound int

-- Set the page bounds
SET @PageLowerBound = @PageSize * @PageIndex
SET @PageUpperBound = @PageLowerBound + @PageSize + 1

-- Create a temp table to store the select results
CREATE TABLE #tmp
(
     RecNo int IDENTITY (1, 1) NOT NULL,
     ArticleID int
)

INSERT INTO #tmp
     SELECT [ID]
     FROM Articles
     ORDER BY PubTime DESC

SELECT A.*
FROM Articles A (nolock), #tmp T
WHERE A.ID = T.ArticleID AND
     T.RecNo > @PageLowerBound AND
     T.RecNo < @PageUpperBound
ORDER BY T.RecNo

GO

另一U可能更适合E序中“拼凑?SQL 语句Q用两次 TOP 命o取得我们所要的分页数据Q例如:Q编?SS2Q?/font>

SELECT * FROM
     (
     SELECT TOP(PageSize) * FROM
     (
          SELECT TOP (PageSize * PageIndex) *
          FROM Articles
          ORDER BY PubTime DESC
     )
     ORDER BY PubTime ASC
)
ORDER BY PubTime DESC

q个的想法就是“掐头去䏀,q有不少分页的方法,q里׃一一列出了?/p>

对于 Oracle 数据库,有几处不同严重妨了上面几个Ҏ的实施,比如QOracle 不支?TOP 关键字:不过q个好像q不十分严重Q因为它提供?rownum q个隐式游标Q可以实C TOP cM的功能,如:

SELECT TOP 10 ... FROM WHERE ...

要写?/p>

SELECT ... FROM ... WHERE ... AND rownum <= 10

rownum 是记录序P1Q?Q?...Q,但有一个比较麻烦的事情是:如果 SQL 语句中有 ORDER BY ... 排序的时候,rownum 居然是先“标号”后排序Q这Pq个序号如果不加处理是不合乎使用需求的?/p>

至于临时表,Oracle 的时表?SQL Server 的有很大不同Q我q没搞懂q个东西Q就不妄加揣了?/p>

国内|站中介l?Oracle 分页的资料很,我找C一个国外站点(www.faqts.comQ的一?FAQQ根据这文章的介绍Q可以如下分:Q编?Ora1Q?/font>

SELECT * FROM
     (
     SELECT A.*, rownum r
     FROM
          (
          SELECT *
          FROM Articles
          ORDER BY PubTime DESC

          ) A
     WHERE rownum <= PageUpperBound
     ) B
WHERE r > PageLowerBound;

其中蓝色部分可以改ؓL的、需要的 SQL SELECT 语句Q这点倒是挺方便的?/p>

 



]]>
SQL Server 索引l构及其使用QZTQ?/title><link>http://www.tkk7.com/wuxufeng8080/articles/91018.html</link><dc:creator>风h?/dc:creator><author>风h?/author><pubDate>Sat, 30 Dec 2006 06:56:00 GMT</pubDate><guid>http://www.tkk7.com/wuxufeng8080/articles/91018.html</guid><description><![CDATA[ <p align="center"> <b>SQL Server 索引l构及其使用Q一Q?br /></b> <br />作者:<a target="_blank">freedk</a></p> <p> <b>一、深入浅出理解烦引结?/b> <br /> <br />  实际上,您可以把索引理解ZU特D的目录。微软的SQL SERVER提供了两U烦引:聚集索引Qclustered indexQ也U聚cȝ引、簇集烦引)和非聚集索引Qnonclustered indexQ也U非聚类索引、非集索引Q。下面,我们举例来说明一下聚集烦引和非聚集烦引的区别Q?br />  其实Q我们的汉语字典的正文本w就是一个聚集烦引。比如,我们要查“安”字Q就会很自然地翻开字典的前几页Q因为“安”的拼音是“an”,而按照拼x序汉字的字典是以英文字母“a”开头ƈ以“z”结Q那么“安”字p然地排在字典的前部。如果您d了所有以“a”开头的部分仍然找不到这个字Q那么就说明您的字典中没有这个字Q同LQ如果查“张”字Q那您也会将您的字典d最后部分,因ؓ“张”的拼音是“zhang”。也是_字典的正文部分本w就是一个目录,您不需要再L其他目录来找到您需要找的内宏V我们把q种正文内容本n是一U按照一定规则排列的目录UCؓ“聚集烦引”?br />  如果您认识某个字Q您可以快速地从自动中查到q个字。但您也可能会遇到您不认识的字,不知道它的发韻Iq时候,您就不能按照刚才的方法找到您要查的字Q而需要去Ҏ“偏旁部首”查到您要找的字Q然后根据这个字后的늠直接d某页来找到您要找的字。但您结合“部首目录”和“检字表”而查到的字的排序q不是真正的正文的排序方法,比如您查“张”字Q我们可以看到在查部首之后的字表中“张”的늠?72,字表中“张”的上面是“驰”字Q但늠却是63,“张”的下面是“徃”字Q页面是390c很昄Q这些字q不是真正的分别位于“张”字的上下方Q现在您看到的连l的“驰、张、徃”三字实际上是他们在非聚集索引中的排序Q是字典正文中的字在非聚集烦引中的映。我们可以通过q种方式来找到您所需要的字,但它需要两个过E,先找到目录中的结果,然后再翻到您所需要的늠。我们把q种目录Ua是目录,正文Ua是正文的排序方式UCؓ“非聚集索引”?br />  通过以上例子Q我们可以理解到什么是“聚集烦引”和“非聚集索引”。进一步引申一下,我们可以很容易的理解Q每个表只能有一个聚集烦引,因ؓ目录只能按照一U方法进行排序?br /><br /><b>二、何时用聚集烦引或非聚集烦?/b><br /><br />下面的表ȝ了何时用聚集烦引或非聚集烦引(很重要)Q?/p> <table id="AutoNumber1" style="COLOR: #000000; BORDER-COLLAPSE: collapse" height="107" cellspacing="0" cellpadding="0" width="62%" border="1"> <tbody> <tr> <td align="middle" width="40%" height="23">动作描述</td> <td align="middle" width="29%" height="23">使用聚集索引</td> <td align="middle" width="31%" height="23">使用非聚集烦?/td> </tr> <tr> <td width="40%" height="20">列经常被分组排序</td> <td width="29%" height="20">?/td> <td width="31%" height="20">?/td> </tr> <tr> <td width="40%" height="20">q回某范围内的数?/td> <td width="29%" height="20">?/td> <td width="31%" height="20">不应</td> </tr> <tr> <td width="40%" height="20">一个或极少不同?/td> <td width="29%" height="20">不应</td> <td width="31%" height="20">不应</td> </tr> <tr> <td width="40%" height="20">数目的不同?/td> <td width="29%" height="20">?/td> <td width="31%" height="20">不应</td> </tr> <tr> <td width="40%" height="20">大数目的不同?/td> <td width="29%" height="20">不应</td> <td width="31%" height="20">?/td> </tr> <tr> <td width="40%" height="20">频繁更新的列</td> <td width="29%" height="20">不应</td> <td width="31%" height="20">?/td> </tr> <tr> <td width="40%" height="20">外键?/td> <td width="29%" height="20">?/td> <td width="31%" height="20">?/td> </tr> <tr> <td width="40%" height="20">主键?/td> <td width="29%" height="20">?/td> <td width="31%" height="20">?/td> </tr> <tr> <td width="40%" height="20">频繁修改索引?/td> <td width="29%" height="20">不应</td> <td width="31%" height="20">?/td> </tr> </tbody> </table> <p>  事实上,我们可以通过前面聚集索引和非聚集索引的定义的例子来理解上表。如Q返回某范围内的数据一V比如您的某个表有一个时间列Q恰好您把聚合烦引徏立在了该列,q时您查?004q??日至2004q?0?日之间的全部数据Ӟq个速度将是很快的Q因为您的这本字典正文是按日期进行排序的Q聚cȝ引只需要找到要索的所有数据中的开头和l尾数据卛_Q而不像非聚集索引Q必d查到目录中查到每一Ҏ据对应的늠Q然后再Ҏ늠查到具体内容?br /><br /><b>三、结合实际,谈烦引用的误区</b><br /><br />  理论的目的是应用。虽然我们刚才列Z何时应用聚集烦引或非聚集烦引,但在实践中以上规则却很容易被忽视或不能根据实际情况进行综合分析。下面我们将Ҏ在实践中遇到的实际问题来谈一下烦引用的误区Q以便于大家掌握索引建立的方法?br /><br />1、主键就是聚集烦?br />  q种xW者认为是极端错误的,是对聚集索引的一U浪贏V虽然SQL SERVER默认是在主键上徏立聚集烦引的?br />  通常Q我们会在每个表中都建立一个ID列,以区分每条数据,q且q个ID列是自动增大的,步长一般ؓ1。我们的q个办公自动化的实例中的列Gid是如此。此Ӟ如果我们这个列设ؓ主键QSQL SERVER会将此列默认集烦引。这样做有好处,是可以让您的数据在数据库中按照IDq行物理排序Q但W者认样做意义不大?br />  显而易见,聚集索引的优势是很明昄Q而每个表中只能有一个聚集烦引的规则Q这使得聚集索引变得更加珍贵?br />  从我们前面谈到的聚集索引的定义我们可以看出,使用聚集索引的最大好处就是能够根据查询要求,q速羃查询范_避免全表扫描。在实际应用中,因ؓIDh自动生成的,我们q不知道每条记录的IDP所以我们很隑֜实践中用IDhq行查询。这׃让ID可个主键作集烦引成ZU资源浪贏V其ơ,让每个ID号都不同的字D作集烦引也不符合“大数目的不同值情况下不应建立聚合索引”规则;当然Q这U情况只是针对用L怿改记录内容,特别是烦引项的时候会负作用,但对于查询速度q没有媄响?br />  在办公自动化pȝ中,无论是系l首|C的需要用L收的文g、会议还是用戯行文件查询等M情况下进行数据查询都M开字段的是“日期”还有用hw的“用户名”?br />  通常Q办公自动化的首会昄每个用户未{收的文件或会议。虽然我们的where语句可以仅仅限制当前用户未{收的情况,但如果您的系l已建立了很长时_q且数据量很大,那么Q每ơ每个用h开首页的时候都q行一ơ全表扫描,q样做意义是不大的,l大多数的用?个月前的文g都已l浏览过了,q样做只能徒增数据库的开销而已。事实上Q我们完全可以让用户打开pȝ首页Ӟ数据库仅仅查询这个用戯3个月来未阅览的文Ӟ通过“日期”这个字D|限制表扫描,提高查询速度。如果您的办公自动化pȝ已经建立?q_那么您的首页昄速度理论上将是原来速度8倍,甚至更快?br />  在这里之所以提到“理Z”三字,是因为如果您的聚集烦引还是盲目地建在IDq个主键上时Q您的查询速度是没有这么高的,即您在“日期”这个字D上建立的烦引(非聚合烦引)。下面我们就来看一下在1000万条数据量的情况下各U查询的速度表现Q?个月内的数据?5万条Q:<br /><br />Q?Q仅在主键上建立聚集索引Qƈ且不划分旉D:</p> <pre>Select gid,fariqi,neibuyonghu,title from tgongwen</pre> <p>用时Q?28470毫秒Q即Q?28U)<br /><br />Q?Q在主键上徏立聚集烦引,在fariq上徏立非聚集索引Q?/p> <pre>select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi> dateadd(day,-90,getdate())</pre> <p>用时Q?3763毫秒Q?4U)<br /><br />Q?Q将聚合索引建立在日期列QfariqiQ上Q?/p> <pre>select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi> dateadd(day,-90,getdate())</pre> <p>用时Q?423毫秒Q?U)<br /><br />  虽然每条语句提取出来的都?5万条数据Q各U情늚差异却是巨大的,特别是将聚集索引建立在日期列时的差异。事实上Q如果您的数据库真的?000万容量的话,把主键徏立在ID列上Q就像以上的W??U情况,在网上的表现就是超ӞҎ无法显C。这也是我摒弃ID列作集烦引的一个最重要的因素。得Z上速度的方法是Q在各个select语句前加Q?/p> <pre>declare @d datetime set @d=getdate()</pre> <p>q在select语句后加Q?/p> <pre>select [语句执行p旉(毫秒)]=datediff(ms,@d,getdate())</pre> <p>2、只要徏立烦引就能显著提高查询速度<br />  事实上,我们可以发现上面的例子中Q第2?条语句完全相同,且徏立烦引的字段也相同;不同的仅是前者在fariqi字段上徏立的是非聚合索引Q后者在此字D上建立的是聚合索引Q但查询速度却有着天壤之别。所以,q是在M字段上简单地建立索引p提高查询速度?br />  从徏表的语句中,我们可以看到q个有着1000万数据的表中fariqi字段?003个不同记录。在此字D上建立聚合索引是再合适不q了。在现实中,我们每天都会发几个文Ӟq几个文件的发文日期q同,q完全符合徏立聚集烦引要求的Q“既不能l大多数都相同,又不能只有极数相同”的规则。由此看来,我们建立“适当”的聚合索引对于我们提高查询速度是非帔R要的?br /><br />3、把所有需要提高查询速度的字D都加进聚集索引Q以提高查询速度<br />  上面已经谈到Q在q行数据查询旉M开字段的是“日期”还有用hw的“用户名”。既然这两个字段都是如此的重要,我们可以把他们合qv来,建立一个复合烦引(compound indexQ?br />  很多为只要把M字段加进聚集索引Q就能提高查询速度Q也有h感到qhQ如果把复合的聚集烦引字D分开查询Q那么查询速度会减慢吗Q带着q个问题Q我们来看一下以下的查询速度Q结果集都是25万条数据Q:Q日期列fariqi首先排在复合聚集索引的v始列Q用户名neibuyonghu排在后列Q:</p> <pre>Q?Qselect gid,fariqi,neibuyonghu,title from Tgongwen where fariqi>''2004-5-5'' </pre> <p>查询速度Q?513毫秒</p> <pre>Q?Qselect gid,fariqi,neibuyonghu,title from Tgongwen             where fariqi>''2004-5-5'' and neibuyonghu=''办公?'</pre> <p>查询速度Q?516毫秒</p> <pre>Q?Qselect gid,fariqi,neibuyonghu,title from Tgongwen where neibuyonghu=''办公?'</pre> <p>查询速度Q?0280毫秒<br /><br />  从以上试验中Q我们可以看到如果仅用聚集烦引的起始列作为查询条件和同时用到复合聚集索引的全部列的查询速度是几乎一LQ甚x用上全部的复合烦引列q要略快Q在查询l果集数目一L情况下)Q而如果仅用复合聚集烦引的非v始列作ؓ查询条g的话Q这个烦引是不vM作用的。当Ӟ语句1?的查询速度一h因ؓ查询的条目数一P如果复合索引的所有列都用上,而且查询l果的话,q样׃形成“烦引覆盖”,因而性能可以辑ֈ最优。同Ӟ误住:无论您是否经怋用聚合烦引的其他列,但其前导列一定要是用最频繁的列?br /><br /><b>四、其他书上没有的索引使用l验ȝ</b><br /><br />1、用聚合索引比用不是聚合索引的主键速度?br />  下面是实例语句:Q都是提?5万条数据Q?/p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''</pre> <p>使用旉Q?326毫秒</p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid<=250000</pre> <p>使用旉Q?470毫秒<br /><br />q里Q用聚合索引比用不是聚合索引的主键速度快了q?/4?br /><br />2、用聚合索引比用一般的主键作order by旉度快,特别是在数据量情况?/p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by fariqi</pre> <p>用时Q?2936</p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by gid</pre> <p>用时Q?8843<br /><br />  q里Q用聚合索引比用一般的主键作order byӞ速度快了3/10。事实上Q如果数据量很小的话Q用聚集索引作ؓ排序列要比用非聚集索引速度快得明显的多Q而数据量如果很大的话Q如10万以上,则二者的速度差别不明显?br /><br />3、用聚合烦引内的时间段Q搜索时间会按数据占整个数据表的癑ֈ比成比例减少Q而无合烦引用了多少个:</p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-1-1''</pre> <p>用时Q?343毫秒Q提?00万条Q?</p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-6-6''</pre> <p>用时Q?170毫秒Q提?0万条Q?/p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16''</pre> <p>用时Q?326毫秒Q和上句的结果一模一栗如果采集的数量一P那么用大于号和等于号是一LQ?/p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen             where fariqi>''2004-1-1'' and fariqi<''2004-6-6''</pre> <p>用时Q?280毫秒<br /><br />4、日期列不会因ؓ有分U的输入而减慢查询速度<br />  下面的例子中Q共?00万条数据Q?004q??日以后的数据?0万条Q但只有两个不同的日期,日期_到日Q之前有数据50万条Q有5000个不同的日期Q日期精到U?/p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen           where fariqi>''2004-1-1'' order by fariqi</pre> <p>用时Q?390毫秒</p> <pre>select gid,fariqi,neibuyonghu,reader,title from Tgongwen             where fariqi<''2004-1-1'' order by fariqi</pre> <p>用时Q?453毫秒<br /><br /><b>五、其他注意事?/b><br /><br />  “水可蝲舟,亦可覆舟”,索引也一栗烦引有助于提高索性能Q但q多或不当的索引也会Dpȝ低效。因为用户在表中每加q一个烦引,数据库就要做更多的工作。过多的索引甚至会导致烦引碎片?br />  所以说Q我们要建立一个“适当”的索引体系Q特别是对聚合烦引的创徏Q更应精益求_,以您的数据库能得到高性能的发挥?br />  当然Q在实践中,作ؓ一个尽职的数据库管理员Q您q要多测试一些方案,扑և哪种Ҏ效率最高、最为有效?br /></p> <img src ="http://www.tkk7.com/wuxufeng8080/aggbug/91018.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/wuxufeng8080/" target="_blank">风h?/a> 2006-12-30 14:56 <a href="http://www.tkk7.com/wuxufeng8080/articles/91018.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>50U方法y妙优化你的SQL Server数据?/title><link>http://www.tkk7.com/wuxufeng8080/articles/86029.html</link><dc:creator>风h?/dc:creator><author>风h?/author><pubDate>Thu, 07 Dec 2006 02:49:00 GMT</pubDate><guid>http://www.tkk7.com/wuxufeng8080/articles/86029.html</guid><description><![CDATA[ <p> <font face="Arial">查询速度慢的原因很多Q常见如下几U:<br />  <br />  1、没有烦引或者没有用到烦?q是查询慢最常见的问题,是程序设计的~陷)<br />  <br />  2、I/O吞吐量小QŞ成了瓉效应?br />  <br />  3、没有创列D查询不优化?br />  <br />  4、内存不?br />  <br />  5、网l速度?br />  <br />  6、查询出的数据量q大Q可以采用多ơ查询,其他的方法降低数据量Q?br />  <br />  7、锁或者死?q也是查询慢最常见的问题,是程序设计的~陷)<br />  <br />  8、sp_lock,sp_who,zd的用h?原因是读写竞争资源?br />  <br />  9、返回了不必要的行和?br />  <br />  10、查询语句不好,没有优化</font> </p> <p> <font face="Arial">  可以通过如下Ҏ来优化查?:<br />  <br />  1、把数据、日志、烦引放C同的I/O讑֤上,增加d速度Q以前可以将Tempdb应放在RAID0上,SQL2000不在支持。数据量Q尺寸)大Q提高I/O重?<br />  <br />  2、纵向、横向分割表Q减表的尺?sp_spaceuse)<br />  <br />  3、升U硬?br />  <br />  4、根据查询条?建立索引,优化索引、优化访问方式,限制l果集的数据量。注意填充因子要适当Q最好是使用默认?Q。烦引应该尽量小Q用字节数的列徏索引好(参照索引的创建),不要Ҏ限的几个值的字段建单一索引如性别字段<br />  <br />  5、提高网?<br />  <br />  6、扩大服务器的内?Windows 2000和SQL server 2000能支?-8G的内存。配|虚拟内存:虚拟内存大小应基于计机上ƈ发运行的服务q行配置。运?Microsoft SQL Server? 2000 Ӟ可考虑虚拟内存大设|ؓ计算Z安装的物理内存的 1.5 倍。如果另外安装了全文索功能,q打运?Microsoft 搜烦服务以便执行全文索引和查询,可考虑Q将虚拟内存大小配置是计算Z安装的物理内存的 3 倍。将 SQL Server max server memory 服务器配|选项配置为物理内存的 1.5 倍(虚拟内存大小讄的一半)?br />  <br />  7、增加服务器 CPU个数;但是必须明白q行处理串行处理更需要资源例如内存。用ƈ行还是串行程是MsSQL自动评估选择的。单个Q务分解成多个dQ就可以在处理器上运行。例如耽搁查询的排序、连接、扫描和GROUP BY字句同时执行QSQL SERVERҎpȝ的负载情况决定最优的q行{Q复杂的需要消耗大量的CPU的查询最适合q行处理。但是更新操作Update,InsertQ?Deleteq不能ƈ行处理?br />  <br />  8、如果是使用likeq行查询的话Q简单的使用index是不行的Q但是全文烦引,耗空间?like 'a%' 使用索引 like '%a' 不用烦引用 like '%a%' 查询Ӟ查询耗时和字D值总长度成正比,所以不能用CHARcdQ而是VARCHAR。对于字D늚值很长的建全文烦引?br />  <br />  9、DB Server 和APPLication Server 分离QOLTP和OLAP分离<br />  <br />  10、分布式分区视图可用于实现数据库服务器联合体。联合体是一l分开理的服务器Q但它们怺协作分担pȝ的处理负荗这U通过分区数据形成数据库服务器联合体的机制能够扩大一l服务器Q以支持大型的多?Web 站点的处理需要。有x多信息,参见设计联合数据库服务器。(参照SQL帮助文g'分区视图'Q?br />  <br />  a、在实现分区视图之前Q必d水^分区?br />  <br />  b、在创徏成员表后Q在每个成员服务器上定义一个分布式分区视图Qƈ且每个视囑օ有相同的名称。这P引用分布式分囑֐的查询可以在M一个成员服务器上运行。系l操作如同每个成员服务器上都有一个原始表的复本一P但其实每个服务器上只有一个成员表和一个分布式分区视图。数据的位置对应用程序是透明的?br />  <br />  11、重建烦?DBCC REINDEX ,DBCC INDEXDEFRAG,收羃数据和日?DBCC SHRINKDB,DBCC SHRINKFILE. 讄自动收羃日志.对于大的数据库不要设|数据库自动增长Q它会降低服务器的性能。在T-sql的写法上有很大的讲究Q下面列出常见的要点Q首先,DBMS处理查询计划的过E是q样的:<br />  <br />  1?查询语句的词法、语法检?br />  <br />  2?语句提交给DBMS的查询优化器<br />  <br />  3?优化器做代数优化和存取\径的优化<br />  <br />  4?由预~译模块生成查询规划<br />  <br />  5?然后在合适的旉提交l系l处理执?br />  <br />  6?最后将执行l果q回l用户其ơ,看一下SQL SERVER的数据存攄l构Q一个页面的大小?K(8060)字节Q?个页面ؓ一个盘区,按照B树存放?br />  <br />  12、Commit和rollback的区?Rollback:回滚所有的事物?Commit:提交当前的事? 没有必要在动态SQL里写事物Q如果要写请写在外面如: begin tran exec(@s) commit trans 或者将动态SQL 写成函数或者存储过E?br />  <br />  13、在查询Select语句中用Where字句限制q回的行?避免表扫?如果q回不必要的数据Q浪费了服务器的I/O资源Q加重了|络的负担降低性能。如果表很大Q在表扫描的期间表锁住Q禁止其他的联接讉K?后果严重?br />  <br />  14、SQL的注释申明对执行没有M影响<br />  15、尽可能不用光标,它占用大量的资源。如果需要row-by-row地执行,量采用非光标技?如:在客L循环Q用临时表,Table变量Q用子查询,用Case语句{等。游标可以按照它所支持的提取选项q行分类Q?只进 必须按照从第一行到最后一行的序提取行。FETCH NEXT 是唯一允许的提取操?也是默认方式。可滚动性可以在游标中Q何地斚w机提取Q意行。游标的技术在SQL2000下变得功能很强大Q他的目的是支持循环。有四个q发选项 READ_ONLYQ不允许通过游标定位更新(Update)Q且在组成结果集的行中没有锁?OPTIMISTIC WITH valueS:乐观q发控制是事务控制理论的一个标准部分。乐观ƈ发控制用于这L情ŞQ即在打开游标及更新行的间隔中Q只有很的Z让第二个用户更新某一行。当某个游标以此选项打开Ӟ没有锁控制其中的行,q将有助于最大化其处理能力。如果用戯图修Ҏ一行,则此行的当前g与最后一ơ提取此行时获取的D行比较。如果Q何值发生改变,则服务器׃知道其他人已更新了此行,q会q回一个错误。如果值是一LQ服务器执行修攏V选择q个q发选项OPTIMISTIC WITH ROW VERSIONING:此乐观ƈ发控刉项Z行版本控制。用行版本控制Q其中的表必d有某U版本标识符Q服务器可用它来定该行在读入游标后是否有所更改。在 SQL Server 中,q个性能?timestamp 数据cd提供Q它是一个二q制数字Q表C数据库中更改的相对序。每个数据库都有一个全局当前旉戛_|@@DBTS。每ơ以M方式更改带有 timestamp 列的行时QSQL Server 先在旉戛_中存储当前的 @@DBTS |然后增加 @@DBTS 的倹{如果某 个表h timestamp 列,则时间戳会被记到行。服务器可以比较某行的当前旉戛_和上次提取时所存储的时间戳|从而确定该行是否已更新。服务器不必比较所有列的|只需比较 timestamp 列即可。如果应用程序对没有 timestamp 列的表要求基于行版本控制的乐观ƈ发,则游标默认ؓZ数值的乐观q发控制?SCROLL LOCKS q个选项实现悲观q发控制。在悲观q发控制中,在把数据库的行读入游标结果集Ӟ应用E序试N定数据库行。在使用服务器游标时Q将行读入游标时会在其上攄一个更新锁。如果在事务内打开游标Q则该事务更新锁一直保持到事务被提交或回滚Q当提取下一行时Q将除去游标锁。如果在事务外打开游标Q则提取下一行时Q锁p丢弃。因此,每当用户需要完全的悲观q发控制Ӟ游标都应在事务内打开。更新锁阻止Q何其它Q务获取更新锁或排它锁Q从而阻止其它Q务更新该行。然而,更新锁ƈ不阻止共享锁Q所以它不会L其它dd行,除非W二个Q务也在要求带更新锁的d。滚动锁Ҏ在游标定义的 Select 语句中指定的锁提C,q些游标q发选项可以生成滚动锁。滚动锁在提取时在每行上获取Qƈ保持Cơ提取或者游标关闭,以先发生者ؓ准。下ơ提取时Q服务器为新提取中的行获取滚动锁Qƈ释放上次提取中行的滚动锁。滚动锁独立于事务锁Qƈ可以保持C个提交或回滚操作之后。如果提交时关闭游标的选项为关Q则 COMMIT 语句q不关闭M打开的游标,而且滚动锁被保留到提交之后,以维护对所提取数据的隔R所获取滚动锁的cd取决于游标ƈ发选项和游?Select 语句中的锁提C。锁提示 只读 乐观数?乐观行版本控?锁定无提C?未锁?未锁?未锁?更新 NOLOCK 未锁?未锁定未锁定 未锁?HOLDLOCK ׃n ׃n ׃n 更新 UPDLOCK 错误 更新 更新 更新 TABLOCKX 错误 未锁?未锁定更新其?未锁?未锁?未锁?更新 *指定 NOLOCK 提示指定了该提示的表在游标内是只ȝ?br />  <br />  16、用Profiler来跟t查询,得到查询所需的时_扑ևSQL的问题所?用烦引优化器优化索引<br />  <br />  17、注意UNion和UNion all 的区别。UNION all?br />  <br />  18、注意用DISTINCTQ在没有必要时不要用Q它同UNION一样会使查询变慢。重复的记录在查询里是没有问题的<br />  <br />  19、查询时不要q回不需要的行、列<br />  <br />  20、用sp_configure 'query governor cost limit'或者SET QUERY_GOVERNOR_COST_LIMIT来限制查询消耗的资源。当评估查询消耗的资源出限制Ӟ服务器自动取消查?在查询之前就扼杀掉?SET LOCKTIME讄锁的旉<br />  <br />  21、用select top 100 / 10 Percent 来限制用戯回的行数或者SET ROWCOUNT来限制操作的?br />  <br />  22、在SQL2000以前Q一般不要用如下的字? "IS NULL", "<>", "!=", "!>", "!<", "NOT", "NOT EXISTS", "NOT IN", "NOT LIKE", and "LIKE '%500'"Q因Z们不走烦引全是表扫描。也不要在Where字句中的列名加函敎ͼ如ConvertQsubstring{?如果必须用函数的时候,创徏计算列再创徏索引来替?q可以变通写法:Where SUBSTRING(firstname,1,1) = 'm'改ؓWhere firstname like 'm%'Q烦引扫描)Q一定要函数和列名分开。ƈ且烦引不能徏得太多和太大。NOT IN会多ơ扫描表Q用EXISTS、NOT EXISTS QIN , LEFT OUTER JOIN 来替代,特别是左q接,而Exists比IN更快Q最慢的是NOT操作.如果列的值含有空Q以前它的烦引不起作用,现在2000的优化器能够处理了。相同的是IS NULLQ?NOT", "NOT EXISTS", "NOT IN"能优化她Q?<>"{还是不能优化,用不到烦引?br />  <br />  23、用Query AnalyzerQ查看SQL语句的查询计划和评估分析是否是优化的SQL。一般的20%的代码占据了80%的资源,我们优化的重Ҏq些慢的地方?br />  <br />  24、如果用了IN或者OR{时发现查询没有走烦引,使用昄x指定索引Q?Select * FROM PersonMember (INDEX = IX_Title) Where processid IN ('?Q??)<br />  <br />  25、将需要查询的l果预先计算好放在表中,查询的时候再Select。这在SQL7.0以前是最重要的手Dc例如医院的住院费计?br />  <br />  26、MIN() ?MAX()能用到合适的索引?br />  <br />  27、数据库有一个原则是代码L据越q越好,所以优先选择Default,依次为Rules,Triggers, ConstraintQ约束如外健dCheckUNIQUE…?数据cd的最大长度等{都是约束),Procedure.q样不仅l护工作,~写E序质量高,q且执行的速度快?br />  <br />  28、如果要插入大的二进制值到Image列,使用存储q程Q千万不要用内嵌Insert来插?不知JAVA是否)。因样应用程序首先将二进制D{换成字符Ԍ寸是它的两倍)Q服务器受到字符后又他转换成二q制?存储q程没有这些动? ҎQCreate procedure p_insert as insert into table(Fimage) values (@image), 在前台调用这个存储过E传入二q制参数Q这样处理速度明显改善?br />  <br />  29、Between在某些时候比IN 速度更快,Between能够更快地根据烦引找到范围。用查询优化器可见到差别?select * from chineseresume where title in ('?,'?) Select * from chineseresume where between '? and '? 是一L。由于in会在比较多次Q所以有时会慢些?br />  <br />  30、在必要是对全局或者局部时表创徏索引Q有时能够提高速度Q但不是一定会q样Q因为烦引也耗费大量的资源。他的创建同是实际表一栗?br />  <br />  31、不要徏没有作用的事物例如生报表时Q浪费资源。只有在必要使用事物时用它?br />  <br />  32、用OR的字句可以分解成多个查询Qƈ且通过UNION q接多个查询。他们的速度只同是否使用索引有关,如果查询需要用到联合烦引,用UNION all执行的效率更?多个OR的字句没有用到烦引,改写成UNION的Ş式再试图与烦引匹配。一个关键的问题是否用到索引?br />  <br />   33、尽量少用视图,它的效率低。对视图操作比直接对表操作慢,可以用stored procedure来代替她。特别的是不要用视图嵌套,嵌套视图增加了寻扑֎始资料的隑ֺ。我们看视图的本质:它是存放在服务器上的被优化好了的已经产生了查询规划的SQL。对单个表检索数据时Q不要用指向多个表的视图,直接从表索或者仅仅包含这个表的视图上读,否则增加了不必要的开销,查询受到q扰.Z加快视图的查询,MsSQL增加了视囄引的功能?br />  <br />  34、没有必要时不要用DISTINCT和ORDER BYQ这些动作可以改在客L执行。它们增加了额外的开销。这同UNION 和UNION ALL一L道理?br />  <br />  select top 20 ad.companyname,comid,position,ad.referenceid,worklocation, convert(varchar(10),ad.postDate,120) as postDate1,workyear,degreedescription FROM jobcn_query.dbo.COMPANYAD_query ad where referenceID in('JCNAD00329667','JCNAD132168','JCNAD00337748','JCNAD00338345',<br />  'JCNAD00333138','JCNAD00303570','JCNAD00303569',<br />  'JCNAD00303568','JCNAD00306698','JCNAD00231935','JCNAD00231933',<br />  'JCNAD00254567','JCNAD00254585','JCNAD00254608',<br />  'JCNAD00254607','JCNAD00258524','JCNAD00332133','JCNAD00268618',<br />  'JCNAD00279196','JCNAD00268613') order by postdate desc<br />  <br />  35、在IN后面值的列表中,出现最频繁的值放在最前面Q出现得最的攑֜最后面Q减判断的ơ数?br />  <br />  36、当用Select INTOӞ它会锁住pȝ?sysobjectsQsysindexes{等)Q阻塞其他的q接的存取。创Z时表时用昄x语句Q而不?select INTO. drop table t_lxh begin tran select * into t_lxh from chineseresume where name = 'XYZ' --commit 在另一个连接中Select * from sysobjects可以看到 Select INTO 会锁住系l表QCreate table 也会锁系l表(不管是时表q是pȝ?。所以千万不要在事物内用它Q!Q这L话如果是l常要用的时表请用实表,或者时表变量?br />  <br />  37、一般在GROUP BY 个HAVING字句之前p剔除多余的行Q所以尽量不要用它们来做剔除行的工作。他们的执行序应该如下最优:select 的Where字句选择所有合适的行,Group By用来分组个统计行QHaving字句用来剔除多余的分l。这样Group By 个Having的开销,查询?对于大的数据行进行分l和Having十分消耗资源。如果Group BY的目的不包括计算Q只是分l,那么用Distinct更快<br />  <br />  38、一ơ更新多条记录比分多ơ更新每ơ一条快,是说批处理?br />  <br />  39、少用时表Q尽量用l果集和TablecL的变量来代替它,Table cd的变量比临时表好<br />  <br />  40、在SQL2000下,计算字段是可以烦引的Q需要满的条g如下Q?br />  <br />  a、计字D늚表达是确定的<br />  <br />  b、不能用在TEXT,NtextQImage数据cd<br />  <br />  c、必配制如下选项 ANSI_NULLS = ON, ANSI_PADDINGS = ON, …?<br />  <br />  41、尽量将数据的处理工作放在服务器上,减少|络的开销Q如使用存储q程。存储过E是~译好、优化过、ƈ且被l织C个执行规划里、且存储在数据库中的SQL语句Q是控制语a的集合,速度当然快。反复执行的动态SQL,可以使用临时存储q程Q该q程Q时表Q被攑֜Tempdb中。以前由于SQL SERVER对复杂的数学计算不支持,所以不得不这个工作放在其他的层上而增加网l的开销。SQL2000支持UDFs,现在支持复杂的数学计,函数的返回g要太大,q样的开销很大。用戯定义函数象光标一h行的消耗大量的资源Q如果返回大的结果采用存储过E?br />  <br />  42、不要在一句话里再三的使用相同的函敎ͼ费资源,结果放在变量里再调用更?br />  <br />  43、Select COUNT(*)的效率教低,量变通他的写法,而EXISTS?同时h意区别: select count(Field of null) from Table ?select count(Field of NOT null) from Table 的返回值是不同的!Q!<br />  <br />  44、当服务器的内存够多Ӟ配制U程数量 = 最大连接数+5Q这栯发挥最大的效率Q否则?配制U程数量<最大连接数启用SQL SERVER的线E池来解?如果q是数量 = 最大连接数+5Q严重的损害服务器的性能?br />  <br />  45、按照一定的ơ序来访问你的表。如果你先锁住表AQ再锁住表BQ那么在所有的存储q程中都要按照这个顺序来锁定它们。如果你Q不l意的)某个存储q程中先锁定表BQ再锁定表AQ这可能׃D一个死锁。如果锁定顺序没有被预先详细的设计好Q死锁很难被发现<br />  <br />  46、通过SQL Server Performance Monitor监视相应g的负?Memory: Page Faults / sec计数器如果该值偶走高,表明当时有线E竞争内存。如果持l很高,则内存可能是瓉?br />  Process:<br />  <br />  1? DPC Time 指在范例间隔期间处理器用在缓延程序调?DPC)接收和提供服务的癑ֈ比?DPC 正在q行的ؓ比标准间隔优先权低的间隔)?׃ DPC 是以Ҏ模式执行的,DPC 旉的百分比为特权时间百分比的一部分。这些时间单独计ƈ且不属于间隔计算L的一?分。这个L昄了作为实例时间百分比的^均忙时?br />  <br />  2?Processor Time计数器 如果该参数值持l超q?5%Q表明瓶颈是CPU。可以考虑增加一个处理器或换一个更快的处理器?br />  <br />  3? Privileged Time 指非闲置处理器时间用于特权模式的癑ֈ比?Ҏ模式是ؓ操作pȝlg和操U늡仉动程序而设计的一U处理模式。它允许直接讉Kg和所有内存。另一U模式ؓ用户模式Q它是一Uؓ应用E序、环境分pȝ和整数分pȝ设计的一U有限处理模式。操作系l将应用E序U程转换成特权模式以讉K操作pȝ服务)。特权时间的 % 包括为间断和 DPC 提供服务的时间。特权时间比率高可能是由于失败设备生的大数量的间隔而引L。这个计数器^均忙时作为样本时间的一部分昄?br />  <br />  4? User Time表示耗费CPU的数据库操作Q如排序Q执行aggregate functions{。如果该值很高,可考虑增加索引Q尽量用简单的表联接,水^分割大表格等Ҏ来降低该倹{?Physical Disk: Curretn Disk Queue Length计数器该值应不超q磁盘数?.5~2倍。要提高性能Q可增加盘?SQLServer:Cache Hit Ratio计数器该D高越好。如果持l低?0%Q应考虑增加内存?注意该参数值是从SQL Server启动后,׃直篏加记敎ͼ所以运行经q一D|间后Q该值将不能反映pȝ当前倹{?br />  <br />  47、分析select emp_name form employee where salary > 3000 在此语句中若salary是Floatcd的,则优化器对其q行优化为Convert(float,3000)Q因?000是个整数Q我们应在编E时使用3000.0而不要等q行时让DBMSq行转化。同样字W和整型数据的{换?br />  <br />  48、查询的兌同写的顺?br />  <br />  select a.personMemberID, * from chineseresume a,personmember b where personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' QA = B ,B = 'L'Q?br />  <br />  select a.personMemberID, * from chineseresume a,personmember b where a.personMemberID = b.referenceid and a.personMemberID = 'JCNPRH39681' and b.referenceid = 'JCNPRH39681' QA = B ,B = 'L'Q?A = 'L'Q?br />  <br />  select a.personMemberID, * from chineseresume a,personmember b where b.referenceid = 'JCNPRH39681' and a.personMemberID = 'JCNPRH39681' QB = 'L'Q?A = 'L'Q?br />  <br />  49?br />  <br />  (1)IF 没有输入负责Z?THEN code1=0 code2=9999 ELSE code1=code2=负责Z?END IF 执行SQL语句? Select 负责人名 FROM P2000 Where 负责Z?gt;=:code1 AND负责Z?<=:code2<br />  <br />  (2)IF 没有输入负责Z?THEN  Select 负责人名 FROM P2000 ELSE code= 负责Z?Select 负责Z?FROM P2000 Where 负责Z?:code END IF W一U方法只用了一条SQL语句,W二U方法用了两条SQL语句。在没有输入负责Z码时,W二U方法显然比W一U方法执行效率高,因ؓ它没有限制条? 在输入了负责Z码时,W二U方法仍然比W一U方法效率高,不仅是少了一个限制条?q因相等q算是最快的查询q算。我们写E序不要怕麻?br />  <br />  50、关于JOBCN现在查询分页的新ҎQ如下)Q用性能优化器分析性能的瓶颈,如果在I/O或者网l的速度上,如下的方法优化切实有效,如果在CPU或者内存上Q用现在的方法更好。请区分如下的方法,说明索引小好?br />  <br />  begin<br />  <br />  DECLARE @local_variable table (FID int identity(1,1),ReferenceID varchar(20))<br />  <br />  insert into @local_variable (ReferenceID)<br />  <br />  select top 100000 ReferenceID from chineseresume order by ReferenceID<br />  <br />  select * from @local_variable where Fid > 40 and fid <= 60<br />  <br />  end ?br />  <br />  begin<br />  <br />  DECLARE @local_variable table (FID int identity(1,1),ReferenceID varchar(20))<br />  <br />  insert into @local_variable (ReferenceID)<br />  <br />  select top 100000 ReferenceID from chineseresume order by updatedate<br />  <br />  select * from @local_variable where Fid > 40 and fid <= 60<br />  <br />  end 的不?br />  <br />  begin<br />  <br />  create table #temp (FID int identity(1,1),ReferenceID varchar(20))<br />  <br />  insert into #temp (ReferenceID)<br />  <br />  select top 100000 ReferenceID from chineseresume order by updatedate<br />  <br />  select * from #temp where Fid > 40 and fid <= 60 drop table #temp<br />  <br />  end</font> </p> <p> <font face="Arial">另附Q存储过E编写经验和优化措施  FromQ网|学网</font> </p> <p> <font face="Arial">  一、适合读者对象:数据库开发程序员Q数据库的数据量很多Q涉及到对SPQ存储过E)的优化的目开发h员,Ҏ据库有浓厚兴的人? </font> </p> <p> <font face="Arial">  二、介l:在数据库的开发过E中Q经怼遇到复杂的业务逻辑和对数据库的操作Q这个时候就会用SP来封装数据库操作。如果项目的SP较多Q书写又没有一定的规范Q将会媄响以后的pȝl护困难和大SP逻辑的难以理解,另外如果数据库的数据量大或者项目对SP的性能要求很,׃遇到优化的问题,否则速度有可能很慢,l过亲nl验Q一个经q优化过的SP要比一个性能差的SP的效率甚至高几百倍? </font> </p> <p> <font face="Arial">  三、内容:  </font> </p> <p> <font face="Arial">  1、开发h员如果用到其他库的Table或ViewQ务必在当前库中建立View来实现跨库操作,最好不要直接用“databse.dbo.table_name”,因ؓsp_depends不能昄SP所使用的跨库table或viewQ不方便校验。  </font> </p> <p> <font face="Arial">  2、开发h员在提交SP前,必须已经使用set showplan on分析q查询计划,做过自n的查询优化检查? </font> </p> <p> <font face="Arial">  3、高E序q行效率Q优化应用程序,在SP~写q程中应该注意以下几点:   </font> </p> <p> <font face="Arial">  a)SQL的用规范:</font> </p> <p> <font face="Arial">   i. 量避免大事务操作,慎用holdlock子句Q提高系lƈ发能力?/font> </p> <p> <font face="Arial">   ii. 量避免反复讉K同一张或几张表,其是数据量较大的表Q可以考虑先根据条件提取数据到临时表中Q然后再做连接?/font> </p> <p> <font face="Arial">   iii. 量避免使用游标Q因为游标的效率较差Q如果游标操作的数据过1万行Q那么就应该改写Q如果用了游标Q就要尽量避免在游标循环中再q行表连接的操作?/font> </p> <p> <font face="Arial">   iv. 注意where字句写法Q必考虑语句序Q应该根据烦引顺序、范围大来定条g子句的前后顺序,可能的让字D顺序与索引序怸_范围从大到小?/font> </p> <p> <font face="Arial">   v. 不要在where子句中的?”左边进行函数、算术运或其他表达式运,否则pȝ可能无法正用烦引?/font> </p> <p> <font face="Arial">   vi. 量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用Q而且count(1)比count(*)更有效率?/font> </p> <p> <font face="Arial">   vii. 量使用?gt;=”,不要使用?gt;”?/font> </p> <p> <font face="Arial">   viii. 注意一些or子句和union子句之间的替?/font> </p> <p> <font face="Arial">   ix. 注意表之间连接的数据cdQ避免不同类型数据之间的q接?/font> </p> <p> <font face="Arial">   x. 注意存储q程中参数和数据cd的关pR?/font> </p> <p> <font face="Arial">   xi. 注意insert、update操作的数据量Q防止与其他应用冲突。如果数据量过200个数据页面(400kQ,那么pȝ会q行锁升U,锁会升成表U锁?  </font> </p> <p> <font face="Arial">  b)索引的用规范:</font> </p> <p> <font face="Arial">   i. 索引的创与应用结合考虑Q徏议大的OLTP表不要超q?个烦引?/font> </p> <p> <font face="Arial">   ii. 可能的使用索引字段作ؓ查询条gQ尤其是聚簇索引Q必要时可以通过index index_name来强制指定烦?/font> </p> <p> <font face="Arial">   iii. 避免对大表查询时q行table scanQ必要时考虑新徏索引?/font> </p> <p> <font face="Arial">   iv. 在用烦引字D作为条件时Q如果该索引是联合烦引,那么必须使用到该索引中的W一个字D作为条件时才能保证pȝ使用该烦引,否则该烦引将不会被用?/font> </p> <p> <font face="Arial">   v. 要注意烦引的l护Q周期性重建烦引,重新~译存储q程。  </font> </p> <p> <font face="Arial">  c)tempdb的用规范:</font> </p> <p> <font face="Arial">   i. 量避免使用distinct、order by、group by、having、join、cumputeQ因些语句会加重tempdb的负担?/font> </p> <p> <font face="Arial">   ii. 避免频繁创徏和删除时表Q减系l表资源的消耗?/font> </p> <p> <font face="Arial">   iii. 在新Z时表Ӟ如果一ơ性插入数据量很大Q那么可以用select into代替create tableQ避免logQ提高速度Q如果数据量不大Qؓ了缓和系l表的资源,先create tableQ然后insert?/font> </p> <p> <font face="Arial">   iv. 如果临时表的数据量较大,需要徏立烦引,那么应该创Z时表和徏立烦引的q程攑֜单独一个子存储q程中,q样才能保证pȝ能够很好的用到该时表的烦引?/font> </p> <p> <font face="Arial">    v. 如果使用C临时表,在存储过E的最后务必将所有的临时表显式删除,先truncate tableQ然后drop tableQ这样可以避免系l表的较长时间锁定?/font> </p> <p> <font face="Arial">    vi. 慎用大的临时表与其他大表的连接查询和修改Q减低系l表负担Q因U操作会在一条语句中多次使用tempdb的系l表。  </font> </p> <p> <font face="Arial">  d)合理的算法用:   </font> </p> <p> <font face="Arial">  Ҏ上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,l合实际应用,采用多种法q行比较,以获得消耗资源最、效率最高的Ҏ。具体可用ASE调优命oQset statistics io on, set statistics time on , set showplan on {?br /></font> </p> <img src ="http://www.tkk7.com/wuxufeng8080/aggbug/86029.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/wuxufeng8080/" target="_blank">风h?/a> 2006-12-07 10:49 <a href="http://www.tkk7.com/wuxufeng8080/articles/86029.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis分页做法QZTQ?/title><link>http://www.tkk7.com/wuxufeng8080/articles/56835.html</link><dc:creator>风h?/dc:creator><author>风h?/author><pubDate>Wed, 05 Jul 2006 09:53:00 GMT</pubDate><guid>http://www.tkk7.com/wuxufeng8080/articles/56835.html</guid><description><![CDATA[以前用ibatis做分늚时?是用的queryforList()ҎQ后面感觉不好,因ؓ我看q一些ibatis的源码,感觉它好像是用resultset的滚动游标的方式实现的,q样如果数据量大会不会有问题呢?以前用jdbc的时候是用一个stringbuffer来构造oracle(我们用的是oracle,其它数据库有各自的方?的三层钳套的sql语句的,做ibatis时语句都是写在xml配置文g里面的,不好做这U构造工作。后来想了葛单的办法:<br />在domain包里面定义一个basedomainc:<br />public class Basedomain {<br /><br />private int start;<br />private int end;<br />/**<br />* @return Returns the end.<br />*/<br />public int getEnd() {<br />return end;<br />}<br />/**<br />* @param end The end to set.<br />*/<br />public void setEnd(int end) {<br />this.end = end;<br />}<br />/**<br />* @return Returns the start.<br />*/<br />public int getStart() {<br />return start;<br />}<br />/**<br />* @param start The start to set.<br />*/<br />public void setStart(int start) {<br />this.start = start;<br />}<br /><br />}<br />包含两个成员变量<br />start: 取数据时的v始位|?br />endQ?取数据时的结束位|?br /><br />然后各个实体cdl承q个basedomainc?br />然后在要分页的sql语句里面加上三层钛_的sql语句Q两个rownum参数分别是上面的start和end?br />以下是一个示例:<br />select * from (select my_table.*,rownum as my_rownum from (<br />select name,password from user<dynamic prepend="WHERE"><isnotempty prepend="AND" property="id"> </isnotempty></dynamic> order by id desc<br /><!--[CDATA[) my_table where rownum<#end# )where my_rownum>=#start#]]--><![CDATA[ ) my_table where rownum<#end# )where my_rownum>=#start# ]]>    <BR>q就是我的ibatis分页的办法,不知道大家觉得如何?呵呵!<BR>br />我的msn:luyongfugx@hotmail.com</html>]]><img src ="http://www.tkk7.com/wuxufeng8080/aggbug/56835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/wuxufeng8080/" target="_blank">风h?/a> 2006-07-05 17:53 <a href="http://www.tkk7.com/wuxufeng8080/articles/56835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Paging of Large Resultsets in ASP.NEThttp://www.tkk7.com/wuxufeng8080/articles/55843.html风h?/dc:creator>风h?/author>Thu, 29 Jun 2006 23:46:00 GMThttp://www.tkk7.com/wuxufeng8080/articles/55843.htmlThe paging of a large database resultset in Web applications is a well known problem. In short, you don't want all the results from your query to be displayed on a single Web page, so some sort of paged display is more appropriate. While it was not an easy task in the old ASP, the DataGrid control in the ASP.NET simplifies this to a few lines of code. So, the paging is easy in ASP.NET, but the default behavior of the DataGrid is that all resulting records from your query will be fetched from SQL server to the ASP.NET application. If your query returns a million records this will cause some serious performance issues (if you need convincing, try executing such a query in your web application and see the memory consumption of the aspnet_wp.exe in the task manager). That's why a custom paging solution is required where desired behavior is to fetch only the rows from the current page.

There are numerous articles and posts concerning this problem and several proposed solutions. My goal here is not to present you with an amazing solves-it-all procedure, but to optimize all the existing methods and provide you with a testing application so you can do evaluation on your own. Here is a good starting point article which describes many different approaches and provides some performance test results:

How do I page through a recordset?

I was not satisfied with the most of them. First, half of the methods use old ADO and are clearly written for the "old" ASP. The rest of the methods are SQL server stored procedures. Some of them yield poor response times as you can see from the author’s performance results at the bottom of the page, but several have caught my attention.

Generalization

The three methods I decided to closely look into are the ones the author calls TempTable, DynamicSQL and Rowcount. I'll refer to the second method as the Asc-Desc method in the rest of this text. I don't think DynamicSQL was a good name, because you can apply dynamic SQL logic to the other methods too. The general problem with all these stored procedures is that you have to assess which columns you'll allow sorting for and that won't probably be just the PK column(s). This leads to a new set of problems ?for each query you want to display via paging you must have as many different paging queries as you have different sorting columns. This means that you will either have a different stored procedure (regardless of the paging method applied) for each sorting column or you'll try to generalize this to only one stored procedure with the help of dynamic SQL. This has a slight performance impact, but increases maintainability if you need to display many different queries using this approach. Thus, I’ll try to generalize all of the stored procedures in this text with dynamic SQL, but in some cases it will be possible to achieve only a certain level of generalization, so you’ll still have to write separate stored procedures for some complex queries.

The second problem with allowing other sorting columns beside the PK column(s) is that if those columns are not indexed in some way, none of these methods will help. In all of them a paged source must be sorted first and the cost of using ordering by non-indexed column is immense for large tables. The response times are so high that all the procedures are practically unusable in this case (the response varies from couple of seconds to couple of minutes depending on the size of the tables and the starting record being fetched). The indexing of other columns brings more performance issues and may be undesirable, for example it might significantly slow you down in a situation where you have a lot of daily imports.

TempTable

The first one I would comment on is the TempTable method. This is actually a widely proposed solution and I encountered it several times. Here is another article that describes it along with the explanation and a sample how to use custom paging with the DataGrid:

ASP.NET DataGrid Paging Part 2 - Custom Paging

The methods in both articles could be optimized with just the Primary Key data copied to the temp table and then doing the join with the main query. Therefore, the essence of this method would be the following

				CREATE
				TABLE #Temp (
    ID intIDENTITYPRIMARYKEY,
    PK  /* here goes PK type */
)

INSERTINTO #Temp SELECT PK FROM Table ORDERBY SortColumn

SELECT ... FROM Table JOIN #Temp temp ON Table.PK = temp.PK ORDERBY temp.ID 
WHERE ID > @StartRow AND ID < @EndRow
The method can be optimized further by copying the rows to the temp table until the end paging row is reached (SELECT TOP EndRow...), but the point is that in the worst case ?for a table with 1 million records you end up with 1 million records in a temp table as well.  Considering all this and having looked upon the results in the article above, I decided to discard this method from my tests.

Asc-Desc

This method uses default ordering in a subquery and then applies the reverse ordering. The principle goes like this

DECLARE @temp TABLE (
    PK  /* PK Type */ NOTNULLPRIMARY 
)

INSERTINTO @temp 
SELECT TOP @PageSize PK FROM (
    SELECT TOP (@StartRow + @PageSize) 
    PK, 
    SortColumn /*If sorting column is defferent from the PK, SortColumn must 
be fetched as well, otherwise just the PK is necessary */ ORDERBY SortColumn /* default order ?typically ASC */) ORDERBY SortColumn /* reversed default order ?typically DESC */ SELECT ... FROM Table JOIN @Temp temp ON Table.PK = temp.PK
ORDERBY SortColumn /* default order */
Full Code ?Paging_Asc_Desc

RowCount

The base logic of this method relies on the SQL SET ROWCOUNT expression to both skip the unwanted rows and fetch the desired ones:

DECLARE @Sort /* the type of the sorting column */
SET ROWCOUNT @StartRow
SELECT @Sort = SortColumn FROM Table ORDERBY SortColumn
SET ROWCOUNT @PageSize
SELECT ... FROM Table WHERE SortColumn >= @Sort ORDERBY SortColumn
Full Code ?Paging_RowCount

SubQuery

There are 2 more methods I’ve taken into consideration, and they come from different resources. The first one is well known triple query or the SubQuery method. The most thorough approach is the one I’ve found in the following article

Server-Side Paging with SQL Server

Although you'll need to be subscribed, a .zip file with the SubQuery stored procedure variations is available. The Listing_04.SELECT_WITH_PAGINGStoredProcedure.txt file contains the complete generalized dynamic SQL. I used a similar generalization logic with all other stored procedures in this text. Here is the principle followed by the link to the whole procedure (I shortened the original code a bit, because a recordcount portion was unnecessary for my testing purposes).

SELECT ... FROM Table WHERE PK IN 
    (SELECT TOP @PageSize PK FROM Table WHERE PK NOT IN
        (SELECT TOP @StartRow PK FROM Table ORDERBY SortColumn)
    ORDERBY SortColumn)
ORDERBY SortColumn
Full Code ?Paging_SubQuery

Cursor

I’ve found the last method while browsing through the Google groups, you can find the original thread here. This method uses a server-side dynamic cursor. A lot of people tend to avoid cursors, they usually have poor performance because of their non-relational, sequential nature. The thing is that paging IS a sequential task and whatever method you use you have to somehow reach the starting row. In all the previous methods this is done by selecting all rows preceding the starting row plus the desired rows and then discarding all the preceding rows. Dynamic cursor has the FETCH RELATIVE option which does the “magic?jump. The base logic goes like this

DECLARE @PK /* PK Type */
DECLARE @tblPK TABLE (
    PK /* PK Type */ NOTNULLPRIMARYKEY
)

DECLARE PagingCursor CURSOR DYNAMIC READ_ONLY FOR
SELECT @PK FROM Table ORDERBY SortColumn

OPEN PagingCursor
FETCH RELATIVE @StartRow FROM PagingCursor INTO @PK

WHILE @PageSize > 0AND @@FETCH_STATUS = 0BEGININSERT @tblPK(PK) VALUES(@PK)
    FETCH NEXT FROM PagingCursor INTO @PK
    SET @PageSize = @PageSize - 1END

CLOSE PagingCursor
DEALLOCATE PagingCursor

SELECT ... FROM Table JOIN @tblPK temp ON Table.PK = temp.PK 
ORDERBY SortColumn
Full Code ?Paging_Cursor

Generalization of Complex Queries

As pointed out before, all the procedures are generalized with dynamic SQL, thus, in theory, they can work with any kind of complex query. Here is a complex query sample that works with Northwind database.

SELECT Customers.ContactName AS Customer, 
       Customers.Address + ', ' + Customers.City + ', ' + 
Customers.Country AS Address, SUM([Order Details].UnitPrice*[Order Details].Quantity) AS
[Total money spent] FROM Customers INNERJOIN Orders ON Customers.CustomerID = Orders.CustomerID INNERJOIN [Order Details] ON Orders.OrderID = [Order Details].OrderID WHERE Customers.Country <> 'USA' AND Customers.Country <> 'Mexico' GROUPBY Customers.ContactName, Customers.Address, Customers.City,
Customers.Country HAVING (SUM([Order Details].UnitPrice*[Order Details].Quantity))>1000ORDERBY Customer DESC, Address DESC
The paging stored procedure call that returns the second page looks like this
EXEC ProcedureName
/* Tables */
'Customers
INNERJOIN Orders ON Customers.CustomerID = Orders.CustomerID
INNERJOIN [Order Details] ON Orders.OrderID = [Order Details].OrderID',
/* PK */
'Customers.CustomerID',
/* ORDERBY */
'Customers.ContactName DESC, Customers.Address DESC',
/* PageNumber */
2,
/* Page Size */
10,
/* Fields */
'Customers.ContactName AS Customer,
Customers.Address + '', '' + Customers.City + '', '' + Customers.Country 
AS Address, SUM([Order Details].UnitPrice*[Order Details].Quantity) AS [Total money spent]', /* Filter */ 'Customers.Country <> ''USA'' AND Customers.Country <> ''Mexico''', /*Group By*/ 'Customers.CustomerID, Customers.ContactName, Customers.Address,
Customers.City, Customers.Country HAVING (SUM([Order Details].UnitPrice*[Order Details].Quantity))>1000'

Note that in the original query, aliases are used in the ORDER BY clause. You can't do that in paging procedures, because the most time-consuming task in all of them is skipping rows preceding the starting row. This is done in various ways, but the principle is not to fetch all the required fields at first, but only the PK column(s) (in case of RowCount method the sorting column), which speeds up this task. All required fields are fetched only for the rows that belong to the requested page. Therefore, field aliases don't exist until the final query, and sorting columns have to be used earlier (in row skipping queries).

The RowCount procedure has another problem, it is generalized to work with only one column in the ORDER BY clause. The same goes for Asc-Desc and Cursor methods, though they can work with several ordering columns, but require that only one column is included in the PK. I guess this could be solved with more dynamic SQL, but in my opinion it is not worth the fuss. Although these situations are highly possible, they are not that frequent. Even if they are, you can always write a separate paging procedure following the principles above.

Performance Testing

I used these 4 methods in my tests, if you have a better one, I’d be glad to know about it. Nevertheless, I wanted to compare these methods and measure their performance. The first thought was to write an ASP.NET test application with paged DataGrid and then measure page response. Still, this wouldn’t reflect the true response time of the stored procedures, so the console application seemed more appropriate. I also included a web application, not for performance testing, but rather as an example of how DataGrid custom paging works with these stored procedures. They are both incorporated in the PagingTest Solution.

I used the auto generated large table for my tests and inserted around 500 000 records in it. If you don’t have a large table to experiment on, you can download the script for a table design and stored procedure for data generation here. I didn't want an identity column for my PK, I used the uniqueidentifier instead. If you'll use this script, you may consider to add an identity after you generate the table. It will add numbers sorted by PK and you'll have an indication that correct page is fetched when you call a paging procedure with PK sorting.

The idea behind performance testing was to call a specific stored procedure many times through a loop and then measure the average response time. Also, in order to remove caching deviations and to model the real situation more accurately ?multiple calls to a stored proc with the same page fetched each time seemed inappropriate. Thus, a random sequence of the same stored procedure with a set of different page numbers was required. Of course, a set of different page numbers assumes fixed number of pages (10 ?20) where each page would be fetched many times, but in a random sequence.

It’s not hard to notice that response times depend on the distance of the fetched page from the beginning of the resultset. The further the starting record is, more records need to be skipped. This is the reason I didn’t include first 20 pages in my random sequence. Instead I used the set of 2N pages. A loop was set to a (number of different pages)*1000. So, every page was fetched around 1000 times (more or less because of a random distribution).

Results

Here are the results I've got - Paging_Results (MS Excell file)




Conclusion

The methods performed in the following order, starting from the best one - RowCount, Cursor, Asc-Desc and Subquery. The behavior in the lower portion was especially interesting, because in many real situations you'll browse beyond the first five pages rarely, so the Subquery method might satisfy your needs in those cases. It all depends on the size of your resultset and the prediction how frequently will the distant pages be fetched. You might use the combination of methods as well. As for myself, I decided to use the RowCount method wherever possible. It beaves quite nice, even for the first page. The "wherever possible" part stands for some cases where it's hard to generalize this method, then I would use the Cursor (possibly combined with the SubQuery for the first couple of pages).

Update 2004-05-05

The main reason I wrote this article was the feedback from the vast programming community. In a couple of weeks I'll be starting work on a new project. The preliminary analysis showed that there's going to be a couple of very large tables involved. These tables will be used in many complex joined queries and their results will be displayed in the ASP.NET application (with sorting and paging enabled). That's why I invested some time in research and pursue for the best paging method. It wasn't just the performance that interested me, but also the usability and maintainability.

Now the invested time has started to pay off already. You can find a post by C. v. Berkel below (many thanks) in which he found a flaw in the RowCount method. It won't work correctly if the sorting column is not unique. The RowCount method performed the best in my tests, but now I am seriously considering not using it at all. In most cases sorting columns (besides the PK) won't be unique. This leaves me with the Cursor method as the fastest and applicable to most situations. It can be combined with the SubQuery method for the first couple of pages and possibly with the RowCount method for unique sorting columns.

Another thing which may be worth mentioning is that there's a tiny flaw in the Asc-Desc method as well. It always returns the PageSize number of records for the last page and not the actual number (which may be lower than the PageSize). The correct number can be calculated but since I don't intend to use this procedure (because of how it performed), I didn't want to improve it any further.

http://www.codeproject.com/aspnet/PagingLarge.asp



]]>
SQL 分页语句http://www.tkk7.com/wuxufeng8080/articles/55805.html风h?/dc:creator>风h?/author>Thu, 29 Jun 2006 11:13:00 GMThttp://www.tkk7.com/wuxufeng8080/articles/55805.html首页的算法很?br /> select top 大?* from 表名 order by 主键

对于带滚动条的表|数据是一一顺序滚动,即拖动滚动条,也可以一页滚动到所选的位置Q当拖动C个新|的算法ؓ
select top 大?* from 表名 where 主键 > 上一|记录的主?order by 主键



]]>
վ֩ģ壺 ձۺϸ| Ƶ| þþþ޾Ʒַɫ| 99þþùƷ| Avۺɫרɫ | 16Ůǿڵ| VAĻһ| Ļĸ | ޾ƷƷԲۿ| ɫһƵѹۿ| ޹һ| һһһëƬëƬ| С˵ͼƬQVOD| 9ѾƷƵ߹ۿ| һѹۿ| պѾƷƵ| 91˾Ʒ޾Ʒ| ޾Ʒ˳3d| 3344߿Ƭ| ŷղ߹ۿ| 18վƵվ| ŮվƵ | þӰԺһ| þù׾ƷѲ| ޾ƷƵѿ| ѻɫëƬƵ| ˾ƷƵȫ| anan߹ۿ| ߳Ƶ| һػɫѴƬƵ| ޶Ƶ˵ӰԺ| ַѹۿ | Ƶվ| ڵֻˬƵ| յӰ߲Ѱ| ޳վ| ޹Ʒպ| 2019Ļֱ| ɫʹۺһ| þù޵Ӱ| ѹۿaƬվ|