使用条件筛选提高查询性能

时间:2018-01-08 21:30:10

标签: sql-server tsql

让我说我有一张300万行的表,表中没有PK也没有索引。

查询如下

SELECT SKU, Store, ColumnA, ColumnB, ColumnC
FROM myTable
WHERE (SKU IN (select * from splitString(@skus)) OR @skus IS NULL)
AND (Store IN (select * from splitString(@stores)) OR @stores IS NULL)

请注意@sku@storeNVARCHAR(MAX),其中包含以逗号分隔的ID列表。 SplitString是一个转换格式为' 1,2,3'的字符串的函数。到1列和3行的表格,如下图所示。

这种模式允许我从应用程序发送参数并通过sku或商店或两者或过滤器过滤。

Description of SplitString

如何提高此查询的效果? - 我知道索引是一个好主意,但我并不是真的知道这些东西,所以对它的指导会很有帮助。 还有其他想法吗?

3 个答案:

答案 0 :(得分:1)

要避免的另一件事是使用Where子句中的函数。这将减慢查询速度。

尝试将它放在脚本的开头,在第一个SELECT之前:

    SELECT skus_group INTO #skus_group 
    FROM  (SELECT item AS skus_group FROM     
    splitstring(@skus, ','))A;

然后替换你的WHERE子句:

    WHERE SKU IN(Select skus_group FROM #skus_group)

这通常可以提高性能,因为它利用索引而不是表扫描,但由于您没有使用任何索引,因此我不确定您将获得多少性能提升。

答案 1 :(得分:1)

这种类型的通用搜索查询在性能上往往很粗糙。

除了使用临时表存储字符串解析结果的建议之外,还有其他一些事情可以做:

添加索引

通常建议每个表都有一个聚集索引(尽管似乎仍有争议的余地):Will adding a clustered index to an existing table improve performance?

除此之外,您可能还想在您正在搜索的字段上添加索引。

在这种情况下,可能是这样的:

  1. SKU(仅针对SKU进行搜索)
  2. 商店,SKU(用于商店搜索以及商店和SKU的组合)
  3. 请记住,如果查询匹配的记录太多,则可能不会使用这些索引。 还要记住,使索引覆盖查询可以提高性能: Why use the INCLUDE clause when creating an index?

    以下是Microsoft有关创建索引的文档的链接: https://docs.microsoft.com/en-us/sql/t-sql/statements/create-index-transact-sql

    使用动态SQL构建查询

    我需要在此前面加上警告。请注意SQL注入,并确保正确编码! How to cleanse dynamic SQL in SQL Server -- prevent SQL injection

    构建动态SQL查询允许您编写更加简化和直接的SQL,从而使优化器能够做得更好。这通常是应该避免的,但我相信它符合这种特殊情况。

    这是一个示例(应根据需要调整以考虑SQL注入):

    DECLARE @sql VARCHAR(MAX) = '
        SELECT SKU, Store, ColumnA
        FROM myTable
        WHERE 1 = 1
    ';
    
    IF @skus IS NOT NULL BEGIN
        SET @sql += ' AND SKU IN (' + @skus + ')';
    END
    
    IF @stores IS NOT NULL BEGIN
        SET @sql += ' AND Store IN (' + @stores + ')';
    END
    
    EXEC sp_executesql @sql;
    

答案 2 :(得分:1)

我相信这会更快地工作:

SELECT SKU, Store, ColumnA, ColumnB, ColumnC FROM myTable WHERE @skus IS NULL AND @stores IS NULL
UNION ALL 
SELECT SKU, Store, ColumnA, ColumnB, ColumnC 
FROM myTable 
INNER JOIN (select colname AS myskus from splitString(@skus))skuses ON skuses.myskus = myTable.SKU
INNER JOIN (select colname AS mystore from splitString(@stores))stores ON stores.mystore = myTable.Store