简体   繁体   English

SQL Server存储过程对200万条记录的排序,分页和筛选

[英]SQL Server Stored Procedure Sorting , Paging and Filtering on 2 million records

I created a stored procedure that select some data from one table 我创建了一个存储过程,该存储过程从一个表中选择了一些数据

table name ( t1 ) columns ( id , a , b ) 表名(t1)列(id,a,b)

CREATE PROCEDURE spGetData
    @DisplayLength INT,
    @DisplayStart INT,
    @SortCol INT,
    @SortDir NVARCHAR(10),
    @Search  NVARCHAR(255) = NULL
AS
BEGIN
    DECLARE @FirstRec INT, @LastRec INT

    SET @FirstRec = @DisplayStart ;
    SET @LastRec = @DisplayStart + @DisplayLength;

    WITH CTE_Employees AS
    (
        SELECT
            ROW_NUMBER() OVER (ORDER BY
                                   CASE WHEN (@SortCol = 0 AND @SortDir = 'asc') THEN id END asc,
                                   CASE WHEN (@SortCol = 0 AND @SortDir = 'desc') THEN id END desc,
                                   CASE WHEN (@SortCol = 1 AND @SortDir = 'asc') THEN a END asc,
                                   CASE WHEN (@SortCol = 1 AND @SortDir = 'desc') THEN a END desc,
                                   CASE WHEN (@SortCol = 2 AND @SortDir = 'asc') THEN b END asc,
                                   CASE WHEN (@SortCol = 2 AND @SortDir = 'desc') THEN b END desc) AS RowNumber, 
            COUNT(*) OVER () AS TotalCount, 
            id, a, b
        FROM
            t1
        WHERE
            (@Search IS NULL 
             OR id LIKE '%' + @Search + '%' 
             OR a LIKE '%' + @Search + '%' 
             OR b LIKE '%' + @Search + '%')
    )
    SELECT * 
    FROM CTE_Employees
    WHERE RowNumber > @FirstRec AND RowNumber <= @LastRec   
END

It takes about 20 seconds to run the following 运行以下程序大约需要20秒

spGetData 1000 ,0,0,'desc'

which is very slow. 这很慢。 This procedure will be called later from an ASP.NET MVC project and the result will be displayed using jQuery datatables. 稍后将从ASP.NET MVC项目中调用此过程,并将使用jQuery数据表显示结果。

How can I improve the performance of it? 如何改善它的性能?

First off, lose CTE. 首先,失去CTE。 This is way too simple query for CTE. 对于CTE,这太简单了。

CREATE PROCEDURE spGetData
    @DisplayLength int,
    @DisplayStart int,
    @SortCol int,
    @SortDir nvarchar(10),
    @Search nvarchar(255) = NULL
AS
BEGIN
    SELECT 
        COUNT(*) OVER () AS TotalCount,
        id,
        a,
        b
    FROM t1
    WHERE 
        (@Search IS NULL OR 
         id LIKE '%'+@Search+'%' OR 
         a LIKE '%'+@Search+'%' OR 
         b LIKE '%'+@Search+'%')
    ORDER BY
        CASE 
            WHEN @SortDir = 'ASC' THEN 
                CASE @SortCol
                    WHEN 0 THEN id
                    WHEN 1 THEN a
                    WHEN 2 THEN b
                END 
            END desc,
        CASE 
            WHEN @SortDir = 'desc' THEN 
                CASE @SortCol
                    WHEN 0 THEN id
                    WHEN 1 THEN a
                    WHEN 2 THEN b
                END 
            END DESC
    OFFSET @DisplayStart ROWS
    FETCH NEXT @DisplayLength ROWS ONLY
END 

This should be faster, but one more remark. 这应该更快,但还要多说一句。 LIKE searching within middle of string ( '%'+@Search+'%' ) can't use any indexing and will always be slow - especially on 2M rows and even worse - doing that on three different columns. 在字符串中间( '%'+@Search+'%' )之内的类似搜索无法使用任何索引,并且总是很慢-尤其是在2M行上,甚至更糟-在三个不同的列上这样做。 It simply has to do a full table scan. 它只需要进行全表扫描。 Adding additional conditions (which are not LIKE) would improve performance. 添加其他条件(不是LIKE)可以提高性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM