3

我有一个表,我想对其进行分页和排序,并且能够获得类似于以下内容的查询来完成工作(真正的查询更多地涉及连接等)。

WITH NumberedPosts (PostID, RowNum) AS
(
    SELECT PostID, ROW_NUMBER() OVER (ORDER BY
        CASE WHEN @sortCol = 'User' THEN User END DESC,
        CASE WHEN @sortCol = 'Date' THEN Date END DESC,
        CASE WHEN @sortCol = 'Email' THEN Email END DESC) as RowNum
   FROM Post
)
INSERT INTO #temp(PostID, User, Date, Email)
SELECT PostID, User, Date, Email
FROM Post
WHERE NumberedPosts.RowNum BETWEEN @start and (@start + @pageSize)
      AND NumberedPosts.PostID = Post.PostID

ORDER BY Date desc问题在于,与普通子句相比,使用 CASE 语句时性能会严重下降(至少减速 10 倍) 。查看查询计划,所有列似乎仍在排序,即使它们与 @sortCol 限定符不匹配。

有没有办法让它以接近“本机”的速度执行?动态 SQL 是解决这个问题的最佳选择吗?谢谢!

4

4 回答 4

3

最好使用三个硬编码查询(在基于@sortCol 的适当 IF 语句中)或动态 SQL 来执行此操作。

您可能可以使用 UNION ALL 三个不同查询(基于执行所有 JOIN 的基本 CTE)来做一个技巧,其中只有一个返回 @sortCol 的行,但我必须在推荐它之前对其进行分析:

WITH BasePosts(PostID, User, Date, Email) AS (
    SELECT PostID, User, Date, Email
    FROM Posts -- This is your complicated query
)
,NumberedPosts (PostID, User, Date, Email, RowNum) AS
(
    SELECT PostID, User, Date, Email, ROW_NUMBER() OVER (ORDER BY User DESC)
    FROM BasePosts
    WHERE @sortCol = 'User'

    UNION ALL

    SELECT PostID, User, Date, Email, ROW_NUMBER() OVER (ORDER BY Date DESC)
    FROM BasePosts
    WHERE @sortCol = 'Date'

    UNION ALL

    SELECT PostID, User, Date, Email, ROW_NUMBER() OVER (ORDER BY Email DESC)
    FROM BasePosts
    WHERE @sortCol = 'Email'
)
INSERT INTO #temp(PostID, User, Date, Email)
SELECT PostID, User, Date, Email
FROM NumberedPosts
WHERE NumberedPosts.RowNum BETWEEN @start and (@start + @pageSize)
于 2010-07-13T00:02:12.727 回答
3

不应该有任何理由查询 post 表两次。您可以走动态路线并解决这些性能问题,或创建由 @sortCol 参数确定的 3 个查询。除了 row_num 和 order by parts 之外的冗余代码,但如果速度很关键,有时你会放弃可维护性。

If @sortCol = 'User' 
Begin
  Select... Order by User
End

If @sortCol = 'Date' 
Begin
  Select .... Order by Date 
end

If @sortCol = 'Email' 
Begin
  Select... Order by Email
End 
于 2010-07-13T00:55:03.223 回答
2

我肯定会走动态 SQL 路线(使用带有参数的 sp_executesql 以避免任何注入攻击)。使用 CASE 方法,您可以立即阻止 SQL Server 使用任何有助于排序过程的相关索引。

于 2010-07-13T00:01:49.960 回答
0

这应该可以工作,但不确定它是否能提高性能:

WITH NumberedPosts (PostID, RowNum) AS
(
    SELECT PostID, ROW_NUMBER() OVER (ORDER BY
        CASE WHEN @sortCol = 'User' THEN User 
             WHEN @sortCol = 'Date' THEN Date
             WHEN @sortCol = 'Email' THEN Email
        END DESC) as RowNum
   FROM Post
)
INSERT INTO #temp(PostID, User, Date, Email)
SELECT PostID, User, Date, Email
FROM Post
WHERE NumberedPosts.RowNum BETWEEN @start and (@start + @pageSize)
      AND NumberedPosts.PostID = Post.PostID
于 2010-07-13T02:54:30.410 回答