【发布时间】:2021-04-18 23:26:28
【问题描述】:
以下代码运行不到一秒:
WITH GRIBS AS
(
SELECT TOP 720
gfm.[ID],
gfm.[FileName],
gfm.[UTCDate] AS [TimeStep]
FROM [hrdps].[GRIBFileMetrics]() gfm
WHERE gfm.[Field] = 'WEARN_SFC_0'
ORDER BY gfm.[UTCDate] DESC
)
SELECT
b.[POIID],
grib.[TimeStep],
AVG(ISNULL(brain.[Amount], 0.0)) AS [Rainfall],
grib.[FileName]
FROM [storm].[BasinRain] brain
LEFT JOIN [storm].[BasinGCSMap] bmap ON brain.[BasinGCSMapID] = bmap.[ID]
LEFT JOIN [storm].[Basin] b ON b.[ID] = bmap.[BasinID]
LEFT JOIN [storm].[POI] poi ON poi.[ID] = b.[POIID]
FULL OUTER JOIN GRIBS grib ON brain.[TimeStep] = grib.[TimeStep]
GROUP BY b.[POIID], grib.[TimeStep], grib.[FileName]
创建 GRIBS 表涉及解析 TVF 中的大字符串,因此任何过滤器或加入它的速度都很慢。这就是我需要 FULL OUTER JOIN 的原因,因为即使没有 Brain.[TimeStep] 值,我也需要 grib.[TimeStep] 值,而反过来查询则需要永远运行。 COALESCE 工作正常,但随后我得到了 brain.[TimeStep] 值超出 grib.[TimeStep] 的范围,这也是不希望的,因为 GRIBS 查询的 TOP 720 ... ORDER BY gfm.[UTCDate] DESC 部分旨在将值限制为最后 30天....
所以我的问题是添加WHERE grib.[TimeStep] IS NOT NULL 或HAVING grib.[TimeStep] IS NOT NULL 会使上面的瞬间查询需要几分钟时间。
但我希望修改查询以排除 grib.[TimeStep] 为空的情况——显然无需在查询中添加任何时间——我总是可以在运行后过滤结果查询并且只添加几微秒,但这并不理想。有什么想法吗?
【问题讨论】:
-
OR性能问题通常可以使用UNION ALL来解决。 -
对于性能问题,您需要添加完整的表和索引定义,并通过brentozar.com/pastetheplan 共享查询计划请解释您理想中想要的确切连接逻辑(性能无法承受,因为我不是清楚。将
GRIBS转储到临时表并加入该表怎么样? -
@Charlieface 临时表的东西可能会起作用。如果我知道什么是表和索引定义以及如何添加它们,我可能会熟练地自己解决这个问题。如果没有人提出更清洁的解决方案,那么将在截止日期前解决这个 javascript 端并测试临时表的想法。
-
这只是一个带有
CREATE TABLE...CREATE INDEX...定义的脚本。在 SSMS 中,您可以右键单击表格并生成脚本。您还可以从 SSMS 获取查询计划。请执行edit 并详细说明所需的连接逻辑。顺便说一句,如果你也添加 TVF,它可能也可以优化。 -
临时表解决方案没什么不干净的,哈哈
标签: sql-server tsql query-optimization