让我说我有一张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
和@store
是NVARCHAR(MAX)
,其中包含以逗号分隔的ID列表。
SplitString是一个转换格式为' 1,2,3'的字符串的函数。到1列和3行的表格,如下图所示。
这种模式允许我从应用程序发送参数并通过sku或商店或两者或过滤器过滤。
如何提高此查询的效果? - 我知道索引是一个好主意,但我并不是真的知道这些东西,所以对它的指导会很有帮助。 还有其他想法吗?
答案 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?
除此之外,您可能还想在您正在搜索的字段上添加索引。
在这种情况下,可能是这样的:
请记住,如果查询匹配的记录太多,则可能不会使用这些索引。 还要记住,使索引覆盖查询可以提高性能: 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