我可以做些什么来提高查询性能吗?我已经包含了执行计划和服务器分析器输出。有索引可以帮忙吗?我发现索引查找需要一些时间,我可以做些什么来帮助解决这个问题吗?在服务器配置文件中,我看到读取次数看起来很高,有什么办法可以帮助解决这个问题吗?
SELECT dbo.Templates.VersionKey
FROM dbo.Templates INNER JOIN
dbo.Indications ON dbo.Templates.Id = dbo.Indications.TemplateId INNER JOIN
dbo.Sentences ON dbo.Indications.SentenceId = dbo.Sentences.Id INNER JOIN
dbo.SentenceParts ON dbo.Sentences.Id = dbo.SentenceParts.SentenceId INNER JOIN
dbo.SentencePartValues ON dbo.SentenceParts.Id = dbo.SentencePartValues.SentencePartId
WHERE (dbo.Templates.Status <> 8) AND
(dbo.Templates.IsCurrentVersion = 1) AND
(dbo.Indications.IsActive = 1) AND
(dbo.Indications.IsCurrentVersion = 1)
AND (NOT (Sentences.[IsDeleted] = 1))
AND (NOT (SentenceParts.[IsDeleted] = 1))
AND (NOT (SentencePartValues.[IsDeleted] = 1))
and
(SUBSTRING(dbo.SentencePartValues.LiteralValue, 12, 36) = 'a2278339-8add-ff3d-8baa-9654b8b8d00b')
是的
不要在 where 子句中使用子字符串:
此查询中的所有时间都花在查找 中的 25,219,726 行
SentencePartValues
,然后将过滤器/子字符串应用于LiteralValue
。当然,说起来很容易,但在实践中却没有多大好处。
进行双通配符
LIKE
搜索可能会更容易,但如果LiteralValue
是 n/varchar(max) 或 sql_variant,那么无论哪种方式你都会被搞砸。您可能需要向表中添加一个计算列,然后为您的查询对其建立适当的索引。
ALTER TABLE dbo.SentencePartValues ADD LV_substring AS TRY_CAST(SUBSTRING(dbo.LiteralValue, 12, 36) AS uniqueidentifier);
或者
ALTER TABLE dbo.SentencePartValues ADD LV_substring AS TRY_CAST(SUBSTRING(dbo.LiteralValue, 12, 36) AS varchar(36));
TRY_CAST
如果某些值最终出现在无法转换的子字符串中,则 uniqueidentifier 可能会失败。添加不带关键字的列
PERSISTED
将防止在添加列时发生长时间阻塞操作。当然,就像我说的,您需要对其进行索引才能使其在一般情况下有用。ONLINE = ON
如果您使用的是企业版,则可以使用,否则您将不得不忽略它并遭受痛苦。