sql 存储过程千万条数据分页
2017-06-30 14:28
375 查看
1.新建表(数据库TestDB)
第一种使用临时变量存储临时表数据,好处使用完不用删除临时表,(微软建议使用此种方法,一般数据不是很大,其实和使用临时表区别不大,只要内存够大就行)
第二种(使用临时表,最后使用完要记得删除。如果表比较大建议先清空表数据,在删除临时表,速度比较快)
此处使用了 INSERT INTO #tmpInfo ..... SELECT ...... FROM Data.TestInfo AS b WITH (NOLOCK) 将数据插入到临时表
第三种(使用临时表,最后使用完要记得删除。如果表比较大建议先清空表数据,在删除临时表,速度比较快)
此处使用了 select * into #table from table 将数据插入到临时表 (此处省略了临时表的创建,据说可以减少sql log日志的记录提高查询速度,没感觉出来,有兴趣可以自己测试)
第四种(使用临时表,最后使用完要记得删除。如果表比较大建议先清空表数据,在删除临时表,速度比较快)
我使用的是拼接sql语句,把不用的 where 条件 直接过滤掉。速度立马提升一大截(条件越多速度越慢)。当然返回的数据结果越多,所使用的时间越久。
从一千多万条数据查询几十万条数据,速度都是1秒级别。
创建 PageRequestParam.cs公共参数分页用到的实体进行封装
创建Mode实体,并继承分页类
C#分页方法,存储过程的调用
USE [TestDB] GO /****** Object: Table [Data].[TestInfo] Script Date: 2017/6/30/周五 13:20:27 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO SET ANSI_PADDING ON GO CREATE TABLE [Data].[TestInfo]( [ID] [INT] IDENTITY(1,1) NOT NULL, [ProcessID] [INT] NOT NULL, [ProductID] [INT] NOT NULL, [StationName] [NVARCHAR](50) NOT NULL, [StationID] [INT] NOT NULL, [StationContent] [NVARCHAR](60) NULL, [ProcessData] [VARCHAR](MAX) NULL, [UpdateTime] [DATETIME] NOT NULL, [Enable] [NVARCHAR](50) NOT NULL, CONSTRAINT [PK_TestInfo_1] PRIMARY KEY CLUSTERED ([ID] ASC )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY] GO SET ANSI_PADDING OFF GO ALTER TABLE [Data].[TestInfo] ADD CONSTRAINT [DF_TestInfo_Enable] DEFAULT (N'NOK') FOR [Enable] GO2.插入一千万条数据(时间比较久,自己可酌情添加数据自己测试)
DECLARE @i INT SET @i=1 WHILE @i<10000000 BEGIN INSERT INTO Data.TestInfo ( ProcessID, ProductID , StationName, StationID , StationContent, UpdateTime) VALUES ( @i ,@i ,'A050' ,0 ,'当前工位代替描述的文本' ,GETDATE()) SET @i=@i+1 END3.存储过程(我自己写了四种方式分页,都能使用,但是第四种效果最好。)
第一种使用临时变量存储临时表数据,好处使用完不用删除临时表,(微软建议使用此种方法,一般数据不是很大,其实和使用临时表区别不大,只要内存够大就行)
USE [TestDB] GO /****** Object: StoredProcedure [dbo].[a_Get_Base_TestInfo] Script Date: 2017/6/30/周五 13:35:18 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /* * 功能描述:获取分页列表 * 创建时间:2017-06-28 * 创建人:LHB exec a_Get_Base_TestInfo -1, -1, '', '', 'NOK', '2015-06-25 09:12', '2017-06-29 09:12:00', 2, 10, null */ ALTER PROCEDURE [dbo].[a_Get_Base_TestInfo] @ProcessID INT --工艺编号 (-1为不作限制) ,@ProductID INT --产品编号 (-1为不作限制) ,@StationName NVARCHAR(100) --工位名称 ,@StationContent NVARCHAR(100) --工位描述 ,@Enable NVARCHAR(100) --是否启用(0:"NOK";1:"OK") ,@StartTime NVARCHAR(50) --开始时间 ,@EndTime NVARCHAR(50) --结束时间 ,@PageIndex INT --当前页码 ,@PageSize INT --分页大小(每页条数) ,@RowCount INT OUTPUT AS --P1.定义临时表,用于存储过滤后的数据 DECLARE @tmpInfo AS TABLE ([ID] [int] ,[ProcessID] [int] ,[ProductID] [int] ,[UpdateTime] [datetime] ,PRIMARY KEY CLUSTERED(ID) ); --P2.把过滤后的数据存储到临时表 INSERT INTO @tmpInfo ([ID] ,[ProcessID] ,[ProductID] ,[UpdateTime]) SELECT b.ID ,b.ProcessID ,b.ProductID ,b.UpdateTime FROM Data.TestInfo AS b WITH (NOLOCK) WHERE (1=1 AND (@ProcessID = -1 OR @ProcessID IS NULL OR b.[ProcessID] = @ProcessID) AND (@ProductID = -1 OR @ProductID IS NULL OR b.[ProductID] = @ProductID) AND (@StationName IS NULL OR LEN(@StationName)=0 or b.StationName LIKE '%'+@StationName+'%') AND (@StationContent IS NULL OR LEN(@StationContent)=0 or b.StationContent LIKE '%'+@StationContent+'%') AND ( @Enable='-1' OR @Enable IS NULL OR LEN(@Enable) = 0 OR b.[Enable]=@Enable) AND (@StartTime IS NULL OR LEN(@StartTime)=0 OR b.UpdateTime >= @StartTime) AND (@EndTime IS NULL OR LEN(@EndTime)=0 OR b.UpdateTime <= @EndTime) ) --P3.获得活动总纪录数 SELECT @RowCount = COUNT(1) FROM @tmpInfo; --P4.数据分页 SELECT g.ID ,g.ProcessID ,g.ProductID ,b.StationName --,b.StationID ,b.StationContent ,g.UpdateTime ,b.[Enable] FROM ( SELECT fp.* ,ROW_NUMBER() OVER (ORDER BY fp.ID DESC) AS RowIndex FROM @tmpInfo AS fp ) g INNER JOIN Data.TestInfo AS b WITH (NOLOCK) ON b.ID = g.ID WHERE g.RowIndex > ((@PageIndex-1)*@PageSize) AND g.RowIndex <=( @PageIndex*@PageSize);
第二种(使用临时表,最后使用完要记得删除。如果表比较大建议先清空表数据,在删除临时表,速度比较快)
此处使用了 INSERT INTO #tmpInfo ..... SELECT ...... FROM Data.TestInfo AS b WITH (NOLOCK) 将数据插入到临时表
USE [TestDB] GO /****** Object: StoredProcedure [dbo].[a_Get_Base_TestInfo_temp] Script Date: 2017/6/30/周五 13:44:41 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /* * 功能描述:获取分页信息列表(使用临时表#table) * 创建时间:2017-06-28 * 创建人:LHB exec a_Get_Base_TestInfo_temp -1, -1, '', '', 'NOK', '2015-06-25 09:12', '2017-06-29 09:12:00', 2, 10, null */ ALTER PROCEDURE [dbo].[a_Get_Base_TestInfo_temp] @ProcessID INT --工艺编号 (-1为不作限制) ,@ProductID INT --产品编号 (-1为不作限制) ,@StationName NVARCHAR(100) --工位名称 ,@StationContent NVARCHAR(100) --工位描述 ,@Enable NVARCHAR(100) --是否启用(0:"NOK";1:"OK") ,@StartTime NVARCHAR(50) --开始时间 ,@EndTime NVARCHAR(50) --结束时间 ,@PageIndex INT --当前页码 ,@PageSize INT --分页大小(每页条数) ,@RowCount INT OUTPUT AS --P1.定义临时表,用于存储过滤后的数据 create table #tmpInfo ([ID] [int] ,[ProcessID] [int] ,[ProductID] [int] ,[UpdateTime] [datetime] ); --P2.把过滤后的数据存储到临时表 INSERT INTO #tmpInfo ([ID] ,[ProcessID] ,[ProductID] ,[UpdateTime] ) SELECT b.ID ,b.ProcessID ,b.ProductID ,b.UpdateTime FROM Data.TestInfo AS b WITH (NOLOCK) WHERE (1=1 AND (@ProcessID = -1 OR b.[ProcessID] = @ProcessID) AND (@ProductID = -1 OR b.[ProductID] = @ProductID) AND (LEN(@StationName)=0 or b.StationName =@StationName) --AND (@StationContent IS NULL OR LEN(@StationContent)=0 or b.StationContent LIKE '%'+@StationContent+'%') AND (LEN(@Enable) = 0 OR b.[Enable]=@Enable) AND (LEN(@StartTime)=0 OR b.UpdateTime >= @StartTime) AND (LEN(@EndTime)=0 OR b.UpdateTime <= @EndTime) ) --P3.获得活动总纪录数 SELECT @RowCount = COUNT(1) FROM #tmpInfo; --P4.数据分页 SELECT g.ID ,b.ProcessID ,b.ProductID ,b.StationName --,b.StationID ,b.StationContent ,b.UpdateTime ,b.[Enable] FROM ( SELECT fp.* ,ROW_NUMBER() OVER (ORDER BY fp.ID DESC) AS RowIndex FROM #tmpInfo AS fp ) g INNER JOIN Data.TestInfo AS b WITH (NOLOCK) ON b.ID = g.ID WHERE g.RowIndex > ((@PageIndex-1)*@PageSize) AND g.RowIndex <=( @PageIndex*@PageSize); --清空临时表数据 (注释:表数据比较大,先清空在删除速度比较快) truncate table #tmpInfo; --删除临时表数据 drop table #tmpInfo;
第三种(使用临时表,最后使用完要记得删除。如果表比较大建议先清空表数据,在删除临时表,速度比较快)
此处使用了 select * into #table from table 将数据插入到临时表 (此处省略了临时表的创建,据说可以减少sql log日志的记录提高查询速度,没感觉出来,有兴趣可以自己测试)
USE [TestDB] GO /****** Object: StoredProcedure [dbo].[a_Get_Base_TestInfo_temp_NoLog] Script Date: 2017/6/30/周五 13:52:44 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /* * 功能描述:获取工艺基础信息列表(减少log,增加速度) * 创建时间:2017-06-28 * 创建人:LHB exec a_Get_Base_TestInfo_temp_NoLog -1, -1, '', '', 'NOK', '2015-06-25 09:12', '2017-06-29 09:12:00', 2, 10, null */ ALTER PROCEDURE [dbo].[a_Get_Base_TestInfo_temp_NoLog] @ProcessID INT --工艺编号 (-1为不作限制) ,@ProductID INT --产品编号 (-1为不作限制) ,@StationName NVARCHAR(100) --工位名称 ,@StationContent NVARCHAR(100) --工位描述 ,@Enable NVARCHAR(100) --是否启用(0:"NOK";1:"OK") ,@StartTime NVARCHAR(50) --开始时间 ,@EndTime NVARCHAR(50) --结束时间 ,@PageIndex INT --当前页码 ,@PageSize INT --分页大小(每页条数) ,@RowCount INT OUTPUT AS --P1.定义临时表,用于存储过滤后的数据 -- create table #tmpInfo -- ([ID] [int], -- [ProcessID] [int], --[ProductID] [int], --[UpdateTime] [datetime] -- ); --P2.把过滤后的数据存储到临时表(select * into #table from table where field='' ) SELECT b.ID --,b.ProcessID --,b.ProductID --,b.UpdateTime INTO #tmpInfo FROM Data.TestInfo AS b WITH (NOLOCK) WHERE (1=1 AND (@ProcessID = -1 OR b.[ProcessID] = @ProcessID) AND (@ProductID = -1 OR b.[ProductID] = @ProductID) AND (LEN(@StationName)=0 or b.StationName=@StationName) --AND (LEN(@StationContent)=0 or b.StationContent LIKE '%'+@StationContent+'%') AND (LEN(@Enable) = 0 OR b.[Enable]=@Enable) AND (LEN(@StartTime)=0 OR b.UpdateTime >= @StartTime) AND (LEN(@EndTime)=0 OR b.UpdateTime <= @EndTime) ) --P3.获得活动总纪录数 SELECT @RowCount = COUNT(1) FROM #tmpInfo; --P4.数据分页 SELECT g.ID ,b.ProcessID ,b.ProductID ,b.StationName --,b.StationID ,b.StationContent ,b.UpdateTime ,b.[Enable] FROM ( SELECT fp. e772 * ,ROW_NUMBER() OVER (ORDER BY fp.ID DESC) AS RowIndex FROM #tmpInfo AS fp ) g INNER JOIN Data.TestInfo AS b WITH (NOLOCK) ON b.ID = g.ID WHERE g.RowIndex > ((@PageIndex-1)*@PageSize) AND g.RowIndex <=( @PageIndex*@PageSize); --清空临时表数据 (注释:表数据比较大,先清空在删除速度比较快) truncate table #tmpInfo; --删除临时表数据 drop table #tmpInfo;
第四种(使用临时表,最后使用完要记得删除。如果表比较大建议先清空表数据,在删除临时表,速度比较快)
我使用的是拼接sql语句,把不用的 where 条件 直接过滤掉。速度立马提升一大截(条件越多速度越慢)。当然返回的数据结果越多,所使用的时间越久。
从一千多万条数据查询几十万条数据,速度都是1秒级别。
USE [TestDB] GO /****** Object: StoredProcedure [dbo].[a_Get_Base_TestInfo_temp_sql] Script Date: 2017/6/30/周五 13:32:55 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO /* * 功能描述:获取工艺基础信息列表(减少log,增加速度) * 创建时间:2017-06-28 * 创建人:LHB exec a_Get_Base_TestInfo_temp_sql -1, -1, '', '', 'NOK', '2015-06-25 09:12', '2017-06-29 09:12:00', 2, 10, null */ ALTER PROCEDURE [dbo].[a_Get_Base_TestInfo_temp_sql] @ProcessID INT --工艺编号 (-1为不作限制) ,@ProductID INT --产品编号 (-1为不作限制) ,@StationName NVARCHAR(100) --工位名称 ,@StationContent NVARCHAR(100) --工位描述 ,@Enable NVARCHAR(100) --是否启用(0:"NOK";1:"OK") ,@StartTime NVARCHAR(50) --开始时间 ,@EndTime NVARCHAR(50) --结束时间 ,@PageIndex INT --当前页码 ,@PageSize INT --分页大小(每页条数) ,@RowCount INT OUTPUT AS --P1.定义临时表,用于存储过滤后的数据 create table #tmpInfo ([ID] [int] -- [ProcessID] [int], --[ProductID] [int], --[UpdateTime] [datetime] ); --P2.把过滤后的数据存储到临时表(select * into #table from table where field='' ) declare @sql NVARCHAR(MAX) ; set @sql ='INSERT INTO #tmpInfo SELECT b.ID FROM Data.TestInfo AS b WITH (NOLOCK) WHERE 1=1 ' IF(@ProcessID>0) begin set @sql= @sql+' AND b.[ProcessID]= '''+cast(@ProcessID AS VARCHAR(20))+'''' end IF(@ProductID>0) begin set @sql= @sql+' AND b.[ProductID]= '''+cast(@ProductID AS VARCHAR(20))+'''' end IF(LEN(@StationName)>0) begin set @sql= @sql+' AND b.[StationName]= '''+@StationName+'''' end IF(LEN(@Enable)>0) begin set @sql= @sql+' AND b.[Enable]= '''+@Enable+'''' end IF(LEN(@StartTime)>0) begin set @sql= @sql+' AND b.[UpdateTime]>= '''+@StartTime+'''' end IF(LEN(@EndTime)>0) begin set @sql= @sql+' AND b.[UpdateTime]<= '''+@EndTime+'''' end EXEC sp_executesql @sql; --P3.获得活动总纪录数 SELECT @RowCount= COUNT(1) FROM #tmpInfo; --P4.数据分页 SELECT g.ID ,b.ProcessID ,b.ProductID ,b.StationName --,b.StationID ,b.StationContent ,b.UpdateTime ,b.[Enable] FROM ( SELECT fp.* ,ROW_NUMBER() OVER (ORDER BY fp.ID DESC) AS RowIndex FROM #tmpInfo AS fp ) g INNER JOIN Data.TestInfo AS b WITH (NOLOCK) ON b.ID = g.ID WHERE g.RowIndex > ((@PageIndex-1)*@PageSize) AND g.RowIndex <=( @PageIndex*@PageSize); --清空临时表数据 (注释:表数据比较大,先清空在删除速度比较快) truncate table #tmpInfo; --删除临时表数据 drop table #tmpInfo;4.调用 存储过程 测试
exec a_Get_Base_TestInfo_temp_sql -1, -1, '', '', 'NOK', '2015-06-25 09:12', '2017-06-29 09:12:00', 2, 10, null5. asp.net 实例调用
创建 PageRequestParam.cs公共参数分页用到的实体进行封装
/// <summary> /// 分页查询参数 /// </summary> public class PageRequestParam { /// <summary> /// 当前页码 /// </summary> public int PageIndex { get; set; } /// <summary> /// 分页大小 /// </summary> public int PageSize { get; set; } /// <summary> /// 起始时间 /// </summary> public string StartTime { get; set; } /// <summary> /// 结束时间 /// </summary> public string EndTime { get; set; } }
创建Mode实体,并继承分页类
/// <summary> /// 测试信息model /// </summary> public class TestInfo:PageRequestParam { public int ID { get; set; } public int ProcessID { get; set; } public int ProductID { get; set; } public string Operation { get; set; } public string StationName { get; set; } public int StationID { get; set; } public string StationContent { get; set; } public string ProcessData { get; set; } //public string CreateDate { get; set; } public string UpdateTime { get; set; } public string Enable { get; set; } }
C#分页方法,存储过程的调用
/// <summary> /// 工艺基础信息 /// </summary> public class basicdataManagement_BPInfo { /// <summary> /// 链接字符串 /// </summary> public string connString = System.Web.Configuration.WebConfigurationManager.AppSettings["ConnectionString"].ToString(); /// <summary> /// 分页工艺基础信息查询 /// </summary> /// <param name="pageSize">当前页</param> /// <param name="pageIndex">当前页</param> /// <param name="totalRecords">总记录</param> /// <param name="totalPages">总页数</param> /// <returns>object</returns> public string getInfoList(TestInfo m) { string json= ""; int totalRecords = 0; using (SqlConnection con = new SqlConnection(connString)) { if (m == null) { return json.ToString(); } //接收分页数据 DataTable dt = new DataTable(); try { con.Open(); SqlCommand cmd = new SqlCommand("a_Get_Base_TestInfo_temp_sql", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add(new SqlParameter("@ProcessID", m.ProcessID)); cmd.Parameters.Add(new SqlParameter("@ProductID", m.ProductID)); cmd.Parameters.Add(new SqlParameter("@StationName", m.StationName)); cmd.Parameters.Add(new SqlParameter("@StationContent", m.StationContent)); cmd.Parameters.Add(new SqlParameter("@Enable", m.Enable)); cmd.Parameters.Add(new SqlParameter("@StartTime", m.StartTime)); cmd.Parameters.Add(new SqlParameter("@EndTime", m.EndTime)); cmd.Parameters.Add(new SqlParameter("@PageIndex", m.PageIndex)); cmd.Parameters.Add(new SqlParameter("@PageSize", m.PageSize)); cmd.Parameters.Add(new SqlParameter("@RowCount", totalRecords)); //设置返回参数 为输出参数OutPut。 cmd.Parameters["@RowCount"].Direction = ParameterDirection.Output; SqlDataAdapter dd = new SqlDataAdapter(cmd); dd.Fill(dt); //获取输出参数 totalRecords = int.Parse(cmd.Parameters["@RowCount"].Value.ToString()); cmd.Parameters.Clear(); json=totalRecords.ToString() } catch (Exception ex) { } return json.ToString(); } } }
相关文章推荐
- 通用的SQL数据分页存储过程
- SQL优化(索引、存储过程、数据分页的存储过程)
- sql存储过程,分页,数据量
- sql 存储过程分页代码 支持亿万庞大数据量
- T-SQL排序,重复数据的剔除保留,分页存储过程
- SQL大数据查询分页存储过程
- sql 分页取数据的存储过程
- GridView分页数据处理,在sql存储过程中取得每页数据
- 发布一个高效的数据分页的存储过程 可以轻松应付百万数据
- 一个高效的数据分页的存储过程 可以轻松应付百万数据
- 通过存储过程访问SQL数据
- T-SQL 存储过程: (修订版) 根据基本表结构及其数据生成 INSERT INTO ... 的 SQL
- [导入][源代码]千万级数据分页存储过程示例!
- 一个将数据分页的存储过程
- DataGrid和存储过程结合的分页,只读取当前页数据
- 发布一个通用的数据分页的存储过程(转载)
- 一个通用的数据分页的存储过程
- [源代码]千万级数据分页存储过程示例!
- 一个将数据分页的存储过程