C#拼接SQL语句,SQL Server 2005+,多行多列大数据量情况下,使用ROW_NUMBER实现的高效分页排序
2012-05-20 23:15
961 查看
如果项目中要用到数据库,铁定要用到分页排序。
之前在做数据库查询优化的时候,通宵写了以下代码,来拼接分页排序的SQL语句。
假设有如下产品表:
Tbl_Product->ID(序号,非空,自增)
Tbl_Product->ProductId(产品Id,主键)
Tbl_Product->ProductName(产品名称,非空)
Tbl_Product->IsDeleted(虚拟删除标记,非空)
调用BasicFunction.GetPagingSQL("Tbl_Product", "ID", "ID,ProductId,ProductName", "IsDeleted=0", "ProductName ASC, ID DESC", 5, 5),BasicFunction为分页排序方法所在的静态类,生成的分页排序SQL语句如下(已手动调整了格式):
查询的字段列表,去掉了不关心的字段(这里为IsDeleted,因为条件里面IsDeleted=0,查出来的产品都是没被删除的);
排序依据,在调用该方法时,应尽量确保排序的依据可以唯一确定记录在结果集中的位置(这里添加了辅助排序依据,ID DESC,如果产品重名,添加的晚的排在前面);
性能优化的一点儿建议:如果字段的值是统计出来的,通常是在视图中,且结果集很大,且需要对结果集分页排序,可以使用临时表规避不稳定的查询效率(关于不稳定的查询效率,会在之后的文章中示例);
另外一点儿建议,使用ROW_NUMBER时,切记一定要和“TOP n”一起使用,n等于int.MaxValue都比不加“TOP n”时要快。
最后,拜托哪位好心人士给测试下性能,拜托了,本人数据库菜鸟,不太懂得数据库的性能测试。
我只知道我对我写的分页排序还是很有信心的,(*^__^*) 嘻嘻!
首发:博客园->剑过不留痕,欢迎转载,前提是注明出处:/article/5399264.html
之前在做数据库查询优化的时候,通宵写了以下代码,来拼接分页排序的SQL语句。
/// <summary> /// 单表(视图)获取分页SQL语句 /// </summary> /// <param name="tableName">表名或视图名</param> /// <param name="key">唯一键</param> /// <param name="fields">获取的字段</param> /// <param name="condition">查询条件(不包含WHERE)</param> /// <param name="collatingSequence">排序规则(不包含ORDER BY)</param> /// <param name="pageSize">页大小</param> /// <param name="pageIndex">页码(从1开始)</param> /// <returns>分页SQL语句</returns> public static string GetPagingSQL( string tableName, string key, string fields, string condition, string collatingSequence, int pageSize, int pageIndex) { string whereClause = string.Empty; if (!string.IsNullOrEmpty(condition)) { whereClause = string.Format("WHERE {0}", condition); } if (string.IsNullOrEmpty(collatingSequence)) { collatingSequence = string.Format("{0} ASC", key); } StringBuilder sbSql = new StringBuilder(); sbSql.AppendFormat("SELECT {0} ", PrependTableName(tableName, fields, ',')); sbSql.AppendFormat("FROM ( SELECT TOP {0} ", pageSize * pageIndex); sbSql.AppendFormat(" [_RowNum_] = ROW_NUMBER() OVER ( ORDER BY {0} ), ", collatingSequence); sbSql.AppendFormat(" {0} ", key); sbSql.AppendFormat(" FROM {0} ", tableName); sbSql.AppendFormat(" {0} ", whereClause); sbSql.AppendFormat(" ) AS [_TempTable_] "); sbSql.AppendFormat(" INNER JOIN {0} ON [_TempTable_].{1} = {0}.{1} ", tableName, key); sbSql.AppendFormat("WHERE [_TempTable_].[_RowNum_] > {0} ", pageSize * (pageIndex - 1)); sbSql.AppendFormat("ORDER BY [_TempTable_].[_RowNum_] ASC "); return sbSql.ToString(); } /// <summary> /// 给字段添加表名前缀 /// </summary> /// <param name="tableName">表名</param> /// <param name="fields">字段</param> /// <param name="separator">标识字段间的分隔符</param> /// <returns></returns> public static string PrependTableName(string tableName, string fields, char separator) { StringBuilder sbFields = new StringBuilder(); string[] fieldArr = fields.Trim(separator).Split(separator); foreach (string str in fieldArr) { sbFields.AppendFormat("{0}.{1}{2}", tableName, str.Trim(), separator); } return sbFields.ToString().TrimEnd(separator); }
假设有如下产品表:
CREATE TABLE [dbo].[Tbl_Product] ( [ID] [int] IDENTITY(1, 1) NOT NULL , [ProductId] [varchar](50) NOT NULL , [ProductName] [nvarchar](50) NOT NULL , [IsDeleted] [int] NOT NULL CONSTRAINT [DF_Tbl_Product_IsDeleted] DEFAULT ( (0) ) , CONSTRAINT [PK_Tbl_Product] PRIMARY KEY CLUSTERED ( [ProductId] ASC ) WITH ( PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] ) ON [PRIMARY]
Tbl_Product->ID(序号,非空,自增)
Tbl_Product->ProductId(产品Id,主键)
Tbl_Product->ProductName(产品名称,非空)
Tbl_Product->IsDeleted(虚拟删除标记,非空)
调用BasicFunction.GetPagingSQL("Tbl_Product", "ID", "ID,ProductId,ProductName", "IsDeleted=0", "ProductName ASC, ID DESC", 5, 5),BasicFunction为分页排序方法所在的静态类,生成的分页排序SQL语句如下(已手动调整了格式):
SELECT Tbl_Product.ID , Tbl_Product.ProductId , Tbl_Product.ProductName FROM ( SELECT TOP 25 [_RowNum_] = ROW_NUMBER() OVER ( ORDER BY ProductName ASC, ID DESC ) , ID FROM Tbl_Product WHERE IsDeleted = 0 ) AS [_TempTable_] INNER JOIN Tbl_Product ON [_TempTable_].ID = Tbl_Product.ID WHERE [_TempTable_].[_RowNum_] > 20 ORDER BY [_TempTable_].[_RowNum_] ASC
查询的字段列表,去掉了不关心的字段(这里为IsDeleted,因为条件里面IsDeleted=0,查出来的产品都是没被删除的);
排序依据,在调用该方法时,应尽量确保排序的依据可以唯一确定记录在结果集中的位置(这里添加了辅助排序依据,ID DESC,如果产品重名,添加的晚的排在前面);
性能优化的一点儿建议:如果字段的值是统计出来的,通常是在视图中,且结果集很大,且需要对结果集分页排序,可以使用临时表规避不稳定的查询效率(关于不稳定的查询效率,会在之后的文章中示例);
另外一点儿建议,使用ROW_NUMBER时,切记一定要和“TOP n”一起使用,n等于int.MaxValue都比不加“TOP n”时要快。
最后,拜托哪位好心人士给测试下性能,拜托了,本人数据库菜鸟,不太懂得数据库的性能测试。
我只知道我对我写的分页排序还是很有信心的,(*^__^*) 嘻嘻!
首发:博客园->剑过不留痕,欢迎转载,前提是注明出处:/article/5399264.html
相关文章推荐
- SQL 2005 ROW_NUMBER() 语句分页 | SQL效率最高的分页查询数据
- SQL Server 2005 启用 xp_cmdshell 使用T-SQL语句导出数据到文件
- sql server 2005 中的利用ROW_NUMBER() 解决数据分页问题
- 使用vs2005的rowNumber对数据实现分页的存储过程。
- sparkSQL里 sql语句,dataframe,Thrift Server JDBC都可以实现对数据的查询,过滤等操作, 哪这3种情况分别是什么情况下使用
- SQL SERVER 2005中使用sql语句对xml 文件和其数据的进行操作(很全面)
- SQL Server分页语句ROW_NUMBER,读取第4页数据,每页10条
- SQL Server 2005 的分页查询(ROW_NUMBER() OVER 语句)
- Sql Server 2005 ROW_NUMBER 函数实现分页
- SQL Server2005使用ROW_NUMBER() OVER实现按分组查询Count()数量排序并分页
- ASP.NET 数据分页第一篇 - 探讨分页原理及 SQL Server 2005 的 ROW_NUMBER 函数
- SQL Server 2005: 利用新的ranking函数实现高效的数据分页操作
- sql 使用row_number()实现分页查询
- 用SQL 2005的ROW_NUMBER() 实现分页功能
- ASP.NET 数据分页第一篇—探讨分页原理及 SQL Server 2005 的 ROW_NUMBER 函数
- oracle12c JSON数据 使用SQL语句实现多表左外连接 显示无效数据 分页查询
- 使用SQL2005 递归查询结合Row_Number()实现完全SQL端树排序
- Sql Server 2005 ROW_NUMBER 函数实现分页
- 用SQL 2005的ROW_NUMBER() 实现分页功能