使用横向连接进行sql搜索非常慢

shstlldc  于 2021-08-01  发布在  Java
关注(0)|答案(1)|浏览(273)

我目前正在我们的一个网格中实现一个搜索函数,这样做时,我的查询从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 = '')

如何优化搜索查询以使其快速运行?实际上,在我的查询中有许多其他的连接和更多的活动,但是我认为这是一个问题,因为当我注解掉名字和姓氏搜索时,我的查询运行得非常快。
感谢所有的帮助。
edit:我也尝试过如下所示的内部连接和子查询,但是这产生了比最初显示的横向连接更糟糕的结果(大约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 = ''
)
ljo96ir5

ljo96ir51#

基于你问题的这一部分,我相信你有一个参数嗅探问题。
我的查询从1秒或更短的时间内运行到16秒左右
请添加 OPTION (RECOMPILE) 到查询的结尾,看看会发生什么(但请调查这一点的含义,并了解cpu的后果)。你也可以看看 OPTIMIZE FOR UNKNOWN 瞎了眼,有几个想法你可以试试
将1个查找减少到 ChildrenWHERE c.datecreated = (select max(c1.datecreated) from children c1 where c1.ParentId = c.ParentId) 打扫房间 @Search 通过简化逻辑

SELECT p.id,
       p.name,
       c.firstname,
       c.lastname
FROM Parents P
    INNER JOIN
    (
        select c1.firstname,
               c1.lastname,
               c1.ParentId,
               row_number() OVER (PARTITION BY c1.ParentId ORDER BY c1.datecreated DESC) as RN
        from children c1
    ) as c
        ON c.ParentId = p.Id
           AND c.RN = 1 --/*Get the Latest First,Lastname based on datecreated*/
    INNER JOIN Users s
        ON p.UserId = s.Id
WHERE 1 = 1
      AND (
              c.firstname = @search
              OR c.lastname = @search
              OR p.name = @search
              -- if @search is either NULL / '' it will return
              OR NULLIF(@search, '') IS NULL
          )
--OPTION (RECOMPILE) /*Uncomment this and see does it improve*/

也只是beaware,你可能会遇到一个参数嗅探问题,即 @search 是一个查询参数,它看起来可能变化很大。
你能试着添加吗 OPTION RECOMPILE 在你询问的最后,看看这是否有区别
如果你还没有这样做,也可以尝试一些事情。
更新表的统计信息
碎片整理/重建索引
看看如何实施ola.hellengren维护计划
最后,为了获得更多帮助,可以使用粘贴查询计划https://www.brentozar.com/pastetheplan/

相关问题