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

时间:2018-10-23 21:33:05

标签: sql sql-server

我创建了一个存储过程,该存储过程从一个表中选择了一些数据

表名(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

运行以下命令大约需要20秒

spGetData 1000 ,0,0,'desc'

这非常慢。稍后将在ASP.NET MVC项目中调用此过程,并使用jQuery数据表显示结果。

如何改善它的性能?

1 个答案:

答案 0 :(得分:0)

首先,失去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 

这应该更快,但要多说一遍。在字符串中间('%'+@Search+'%')中的LIKE搜索不能使用任何索引,并且总是很慢-尤其是在2M行上,甚至更糟-在三个不同的列上这样做。它只需要进行全表扫描。 添加其他条件(不是LIKE)可以提高性能。