HCh*_* Le 5 performance index sql-server select like
我有下面的 select 语句,结果非常慢(41 秒)
SELECT DISTINCT a.Doc_Resource_ID
,a.Parent_ID
,a.Logical_Path
,a.lvl
,CAST(SUBSTRING(a.Security_Level, 21, 1) AS TINYINT)
FROM Doc_ACL_Detail_D a
WHERE a.UserId = @I_vUserId
AND @I_vParentId = 0
OR (Logical_Path LIKE(CASE
WHEN @I_vParentId>0 THEN '%-'+LTRIM(STR(@I_vParentId))
END)
OR Logical_Path LIKE(CASE
WHEN @I_vParentId>0 THEN '%-'+LTRIM(STR(@I_vParentId))+'-%'
END ))
OPTION (MAXRECURSION 5000)
Run Code Online (Sandbox Code Playgroud)
我已经为表创建了非聚集索引Doc_ACL_Detail_D,但执行计划仍然是表扫描。
我创建的索引:
CREATE NONCLUSTERED INDEX idx_Doc_ACL_Detail_D_UserId_Logical_Path
ON [dbo].[Doc_ACL_Detail_D] ([UserId],[Logical_Path])
INCLUDE (Parent_ID,Doc_Resource_ID,lvl,Security_Level)
Run Code Online (Sandbox Code Playgroud)
有人可以帮我优化这个语句吗?十分感谢。
Phi*_* W. 17
就目前的数据而言,没有任何索引可以提供帮助。
您要查找的值嵌入在字段内的某个位置,而不是在字段的开头(索引可以提供帮助)。由于数据库不知道字段开头的内容,因此它无法导航到索引的正确位以获取所需的记录。
反转值并对这些值建立索引将有助于值位于字段末尾的位置,但仍然无助于值卡在中间某处的位置。
对我来说,这个领域的数据“太多”了。您正在使用字符串操作函数来提取部分值,这对我来说,您真正想要的值被“包装”在“噪声”中。 消除噪音可能是一个更好的选择。
select *
from Folders ;
+----+--------+------+
| id | parent | path |
+----+--------+------+
| 1 | NULL | abc | The folder /abc
| 2 | 1 | def | /abc/def
| 3 | 2 | ghi | /abc/def/ghi
+----+--------+------+
Run Code Online (Sandbox Code Playgroud)
递归地遍历这个结构要容易得多。
另外,请考虑删除distinct.
我经常看到,distinct 被用作“膏药”来掩盖数据结构本身或查询的潜在问题,例如结果中出现的“重复”行(通常是由错误的联接引起的),但是“使用不同的东西会让它们消失”。摆脱这些“重复项”可能会对数据库造成巨大的消耗(“选择不同的 a,b,c,d”的表现与“按 a,b,c,d 排序 a,b,c, d"),所以最好解决根本原因。