【发布时间】:2020-07-01 14:21:22
【问题描述】:
我目前正在我们的一个网格中实现搜索功能,这样做时,我的查询从 1 秒或更短的时间运行到大约 16 秒的运行时间(我添加了建议的索引等)。此查询返回的数据将是父母的 id、父母的姓名、最近的孩子的名字和最近的孩子的姓。以下简化查询运行速度极慢(超过 15 秒),但运行正常:
SELECT
p.id
,p.name
,c.firstname
,c.lastname
FROM Parents p
CROSS APPLY (
SELECT TOP (1)
c.firstname
,c.lastname
FROM Children c
WHERE c.ParentId = p.Id
ORDER BY c.datecreated DESC
) i
INNER JOIN Users s
ON p.UserId = u.Id
WHERE (
@search IS NOT NULL
AND @search != ''
AND (
@search = c.firstname
OR @search = c.lastname
OR p.name = @search
)
OR @search IS NULL
OR @search = ''
)
以下查询(注意不包括名字和姓氏搜索)运行速度很快,但缺少所需的功能:
SELECT
p.id
,p.name
,c.firstname
,c.lastname
FROM Parents p
CROSS APPLY (
SELECT TOP (1)
c.firstname
,c.lastname
FROM Children c
WHERE c.ParentId = p.Id
ORDER BY c.datecreated DESC
) i
INNER JOIN Users s
ON p.UserId = u.Id
WHERE (
@search IS NOT NULL
AND @search != ''
AND p.name = @search
)
OR (@search IS NULL)
OR (@search = '')
如何优化我的搜索查询以使其快速运行?在实践中,我的查询中有许多其他联接和更多活动,但是我认为这是问题所在,因为当我注释掉名字和姓氏搜索时,我的查询运行得非常快。
感谢所有帮助。
编辑:我也尝试过如下所示的内部连接和子查询,但是这产生的结果比最初显示的横向连接尝试更糟糕(执行时间约为 25 秒)
SELECT
p.id,
p.name,
c.firstname,
c.lastname
from Parents P
INNER JOIN children c
ON c.ParentId = p.Id
INNER JOIN Users s
ON p.UserId = s.Id
WHERE c.datecreated = (
select max(c1.datecreated) from children c1 where c1.ParentId = c.ParentId
)
and @search IS NOT NULL
AND @search != ''
AND (
@search = c.firstname
OR @search = c.lastname
OR p.name = @search
)
OR @search IS NULL
OR @search = ''
)
【问题讨论】:
-
第一个查询应该做什么?返回最近创建的 Children 记录具有匹配名称的父母(这是查询所做的)或返回至少有一个具有匹配名称的孩子的父母(这似乎是您想要的)。
-
返回的数据应该是所有父母的姓名和ID以及他们最近孩子的名字和姓氏。那么孩子的名字和姓氏应该是可搜索的。 @BaconBits 这更有意义吗?
-
使用“catch all”查询通常会生成一个相当糟糕的计划,因为优化器会在提供@search 时生成一个计划,但相同的计划在任何其他情况下都不起作用案例。常见的解决方案是使用动态 SQL 来完全避免多个 OR。我还建议先过滤名称,然后检查孩子是否是最新的。
-
@EzLo 您有任何示例或链接可以使这些建议更清晰吗?您将上述查询的哪一部分称为“全部”查询
标签: sql sql-server tsql