SQL-优化复杂分页搜索查询

SQL-优化复杂分页搜索查询,sql,database,optimization,stored-procedures,paging,Sql,Database,Optimization,Stored Procedures,Paging,我目前正在为大型数据库中的复杂搜索开发一个存储过程。因为有数千个条目可以返回,所以我想使用分页。虽然它在工作,但我认为它太慢了。我读了很多关于SQL查询分页和优化性能的文章。但大多数“优化”只对非常基本的请求有用,比如“从表x中提供20-30项” 由于我们的世界并不是那么简单,而且还有更复杂的查询需要进行,因此我希望获得一些帮助,以优化以下查询: CREATE PROCEDURE [SearchItems] @SAttr1 BIT = 0, @SAttr2 BIT = 0, @SAttr3 BI

我目前正在为大型数据库中的复杂搜索开发一个存储过程。因为有数千个条目可以返回,所以我想使用分页。虽然它在工作,但我认为它太慢了。我读了很多关于SQL查询分页和优化性能的文章。但大多数“优化”只对非常基本的请求有用,比如“从表x中提供20-30项”

由于我们的世界并不是那么简单,而且还有更复杂的查询需要进行,因此我希望获得一些帮助,以优化以下查询:

CREATE PROCEDURE [SearchItems]
@SAttr1 BIT = 0,
@SAttr2 BIT = 0,
@SAttr3 BIT = 0,
@Flag1 BIT = 0,
@Flag2 BIT = 0,
@Param1 VARCHAR(20),
@Param2 VARCHAR(10),
@SkipCount BIGINT,
@TakeCount BIGINT,
@SearchStrings NVARCHAR(1000)    
AS
    DECLARE @SearchStringsT TABLE(
        Val NVARCHAR(30)
    )

    INSERT INTO @SearchStringsT 
    SELECT * FROM dbo.Split(@SearchStrings,',');

WITH ResultTable AS (
    SELECT  Table1.*, ROW_NUMBER() OVER(ORDER BY Table1.ID ASC) AS [!ROWNUM!]
    FROM Table1
    INNER JOIN Table2 ON Table1.ID = Table2.FK1
    INNER JOIN Table3 ON Table2.ID = Table3.FK2
    INNER JOIN Table4 ON Table3.XX = Table4.FKX
    WHERE Table1.X1 = @Parameter1
    AND
        (@Flag1 = 0 OR Table1.X2 = 1) AND
        (@Flag2 = 0 OR Table2.X4 = @Parameter2) AND
        (@Flag3 = 0 OR EXISTS(SELECT * FROM Table5 WHERE Table5.ID = Table3.X1)) 
    AND
    (                   
        (@SAttr1 = 0 OR EXISTS(SELECT * FROM @SearchStringsT WHERE Table1.X1 LIKE Val)) OR
        (@SAttr2 = 0 OR EXISTS(SELECT * FROM @SearchStringsT WHERE Table2.X1 LIKE Val)) OR
        (@SAttr3 = 0 OR EXISTS(SELECT * FROM @SearchStringsT WHERE Table3.X1 LIKE Val)) OR
        (@SAttr4 = 0 OR EXISTS(SELECT * FROM @SearchStringsT WHERE Table4.X1 LIKE Val))
    )
)
SELECT TOP(@TakeCount) * FROM ResultTable
WHERE [!ROWNUM!] BETWEEN (@SkipCount + 1) AND (@SkipCount + @TakeCount)
RETURN
@SAttr参数是位参数,用于指定是否搜索字段,@Flag参数用于打开/关闭某些布尔表达式的检查,@SkipCount和@TakeCount用于分页@SearchString是一个逗号分隔的搜索关键字列表,已经包含通配符

我希望有人能帮助我优化这一点,因为在主表中有20000个条目的数据库中,单个搜索持续800毫秒,并且随着条目数的增加而增加。最终的应用程序需要处理超过100000个条目

我非常感谢你的每一次帮助。
标记

存储过程不太擅长超级通用,因为它会阻止SQL Server始终使用最佳方法。在类似的情况下,我最近使用了(gasp)动态SQL。我的搜索存储过程将构建SQL代码来执行搜索,使用分页,就像使用它一样(使用行号()等)。这样做的好处是,如果参数表明搜索中没有使用一条信息,那么生成的代码将忽略它。最后,它允许更好的查询计划


确保正确使用sp_executesql来防止SQL注入攻击。

虽然我同意Tom H的观点,但这可能是动态SQL最好的情况(我是一个存储过程类型的女孩,所以我不经常这么说),可能是表上没有很好的索引。是否所有可能的搜索字段都已编制索引?所有的FK都索引了吗

我的意思是20000是一个非常小的表,100000也是一个非常小的表,所以看起来你可能还没有建立索引


检查执行计划以查看是否正在使用索引

请确保首先阅读此内容并同意您的看法此特定任务可能在动态SQl中完成得更好。@HLGEM-谢谢,我开始寻找链接将其发布到此处,然后被一个闪亮的对象分散了注意力:)对我来说,使用存储过程的主要原因是用户权限管理,因此具有安全性优势。你不觉得有些“@Flag=0”或“@Flag=0”比每次执行搜索时向数据库发送如此大的查询更快吗?向数据库发送查询几乎不需要任何资源。网络上只有几个字节。当然,无论如何我都不是这样做的。我调用了一个与您完全相同的存储过程,但在该存储过程中,我构建了要运行的SQL。使用@Flag=0或逻辑不起作用,因为SQL Server无法提前说明该条件-它仍然会创建一个查询计划,好像必须检查第二个条件一样,这通常会导致表扫描。@Tom H。-感谢您提供有关查询计划的信息。是否不可能打开/关闭字段检查?您是对的。我现在几乎没有索引,但这是因为插入操作比读取操作多。由于索引降低了插入的速度,我认为使用索引不会带来总体性能上的好处。但我必须对此进行一些分析。现在我已经将所有主键作为聚集索引(用于连接),将所有FK、“order by”或“where”列作为未聚集索引。查询速度没有显著变化。还有其他建议吗?