代码之家  ›  专栏  ›  技术社区  ›  TheEmirOfGroofunkistan

生成sql查询计划需要5分钟,查询本身以毫秒为单位运行。怎么了?

  •  10
  • TheEmirOfGroofunkistan  · 技术社区  · 16 年前

    我有一个在sql server 2008上运行的相当复杂(或者难看,取决于您如何看待它)的存储过程。它基于一个具有pk表和fk表的视图。fk表左键与pk表的连接略多于30次(fk表的设计很差-它使用名称-值对,我需要将其展平)。不幸的是,这是第三方,我不能改变它)。

    不管怎么说,这几周一直很好,直到我周期性地注意到一次需要3-5分钟的跑步。事实证明,这是生成查询计划所需的时间。一旦查询计划存在并被缓存,存储过程本身就会非常高效地运行。在有理由重新生成并再次缓存查询计划之前,一切都会顺利进行。

    有人看到这个吗?为什么要花这么长时间来制定计划?有没有办法让它更快地想出一个计划?

    3 回复  |  直到 16 年前
        1
  •  2
  •   gbn    16 年前

    某些事情会导致计划需要重新编译,例如统计信息更新或ddl更改。 列表如下: Execution Plan Caching and Reuse

    当前表单中的查询总是需要3-5分钟才能重新编译:这是不可避免的。

    假设您不能更改它(pivot、使用触发器维护“正确”的表等),那么您只能控制重新编译的发生时间。

    雷莫斯的计划指南回答是一个办法。我也会查看我的统计维护并确保它是在一夜之间完成的,比如说,所以它只在一天的开始发生一次

        2
  •  3
  •   Remus Rusanu    16 年前

    你可以尝试使用 Plan Guide . 计划生成仍将持续一段时间,但应大大缩短。

        3
  •  2
  •   Aleksei Lychev    16 年前

    你有没有考虑过像这样将30个join select重写为smth?

    SELECT [key], NULL AS [a], NULL AS [b]
      INTO #temp
      FROM [pk-table]
    
    UPDATE t SET t.[a] = fk.[a], t.[b] = fk.[b]
      FROM #temp t
      INNER JOIN (
        SELECT f.[key],
          MAX(CASE WHEN f.[name] = 'a' THEN f.[value] ELSE NULL END) AS [a],
          MAX(CASE WHEN f.[name] = 'b' THEN f.[value] ELSE NULL END) AS [b]
        FROM [fk-table] f
        GROUP BY f.[key]
        ) fk ON (fk.[key] = t.[key]
    

    尽管这可能不是你最初问题的答案:)

    推荐文章