优化长时间运行的SQL Server查询
我有以下疑问:优化长时间运行的SQL Server查询,sql,sql-server,performance,query-optimization,Sql,Sql Server,Performance,Query Optimization,我有以下疑问: SELECT fpa.scenario_id, fpa.facility_id, cge.CostGroupId result_total_id, mp_surrogate_id, CAST(SUM(fpa.raw_amount * cge.CostSign) AS DECIMAL(25, 13)) result_total_amount INTO ADM_FactProfitTotalAmount_1 FROM #tempAmo
SELECT fpa.scenario_id,
fpa.facility_id,
cge.CostGroupId result_total_id,
mp_surrogate_id,
CAST(SUM(fpa.raw_amount * cge.CostSign) AS DECIMAL(25, 13))
result_total_amount
INTO ADM_FactProfitTotalAmount_1
FROM #tempAmount fpa
JOIN ResultTest cge ON cge.CostId = fpa.process_id
WHERE fpa.scenario_id = 1
GROUP BY fpa.scenario_id, fpa.facility_id, cge.CostGroupId, fpa.mp_surrogate_id
在数量上,我有2.2亿行。
在ResultSet中,我有150行。
我有一个关于tempAmount的索引:
执行大约需要1小时。有可能优化它吗
编辑:
我已经在ResultSet列CostId上创建了索引,对其他索引和查询做了一些更改
CREATE CLUSTERED INDEX #tempFactAmount_index
ON #tempAmount (process_id ,facility_id, mp_surrogate_id )
SELECT ISNULL(CAST(1 as BIGINT), 0) scenario_id,
fpa.facility_id,
cge.CostGroupId result_total_id,
fpa.mp_surrogate_id,
CAST(SUM(fpa.raw_amount * cge.CostSign) AS DECIMAL(25, 13)) result_total_amount
INTO ADM_FactProfitTotalAmount_1
FROM ResultTest cge
JOIN #tempAmount fpa ON cge.CostId = fpa.process_id
GROUP BY fpa.facility_id, fpa.mp_surrogate_id, cge.CostGroupId
执行计划:
41%插入ADM\u FactProfitTotalAmount\u 1
51%哈希匹配聚合
2%哈希匹配内部联接
我建议从检查估计的执行计划开始。
多列索引只能在其前缀为左时使用。
所以我建议将进程id移到场景id旁边,因为它们用于where和join
创建非聚集索引tempaument\u进程\u id
在tempAmountscenario\u id、process\u id、facility\u id、mp\u Subrogate\u id上
最后一点:让操作系统尽可能多地将磁盘块缓存到内存中。
在linux中,在一些性能关键型数据库投入生产之前,
不要编辑您的\u database.store.file>/dev/null。
大量磁盘读取将从内存缓存中命中
首先,我建议捕获实际的执行计划。如果正在从SQL Server Management Studio SSMS运行查询,请启用“包括实际执行计划”选项。如果此查询是从其他程序运行的,请运行SQL Server探查器并打开Showplan统计配置文件和/或Showplan XML统计配置文件。查看此配置文件,并查看查询的行为是否符合预期 你有关于ResultSet ColumCostid的索引吗?由于只有150行,对这个表进行索引扫描并不是什么大问题。如果此表上没有索引,可以尝试使用 我想知道执行计划是否正在执行嵌套循环以连接到ResultSet。如果是这样,那将是150 X 220000000=330亿次运营。如果是这种情况,哈希连接或合并连接的性能会更好。您可以使用连接提示选项HASH join或选项MERGE join强制特定的连接。单凭这一点就可以产生巨大的变化
tempAmount上的索引有许多列,这些列对于SELECT查询是不必要的。此外,它是一个非聚集索引。还有聚集索引吗?若并没有,您可以尝试将其转换为集群,并去掉其他列。这将减少索引的大小,并且性能会更好,因为场景id的所有行都是连续的。在这样的场景中,我发现在连接到较小的表之前将较大表中的金额相加通常会有所帮助。因此,在本例中,我将使用以下内容:
;WITH SUMCTE
AS
(
SELECT fpa.facility_id,
fpa.mp_surrogate_id,
fpa.process_id,
SUM(fpa.raw_amount) AS total_amount
FROM #tempAmount fpa
GROUP BY fpa.facility_id, fpa.mp_surrogate_id, fpa.process_id
)
SELECT CAST(1 as BIGINT) AS Scenario_id,
facility_id,
cge.CostGroupId result_total_id,
mp_surrogate_id,
CAST(SUM(SCT.total_amount * cge.CostSign) AS DECIMAL(25, 13)) result_total_amount
INTO ADM_FactProfitTotalAmount_1
FROM ResultTest cge
JOIN SUMCTE SCT ON cge.CostId = SCT.process_id
GROUP BY fpa.facility_id, fpa.mp_surrogate_id, cge.CostGroupId
如果每个进程id的ResultTest中只有一行,我将通过以下方式删除外部组来进一步简化:
;WITH SUMCTE
AS
(
SELECT fpa.facility_id,
fpa.mp_surrogate_id,
fpa.process_id,
SUM(fpa.raw_amount) AS total_amount
FROM #tempAmount fpa
GROUP BY fpa.facility_id, fpa.mp_surrogate_id, fpa.process_id
)
SELECT CAST(1 as BIGINT) AS Scenario_id,
facility_id,
cge.CostGroupId result_total_id,
mp_surrogate_id,
CAST((SCT.total_amount * cge.CostSign) AS DECIMAL(25, 13)) result_total_amount
INTO ADM_FactProfitTotalAmount_1
FROM ResultTest cge
JOIN SUMCTE SCT ON cge.CostId = SCT.process_id
您是否也有进程id的索引?从连接条件来看,定义一个连接似乎是有益的。将进程id移动到第二个索引列也会有所帮助。但是,如果没有查询计划,很难判断瓶颈在哪里。关于优化选择的良好网络广播:尝试在tempAmount上仅在列scenario_id上创建聚集索引。fpa.schenario_id=1的选择性有多高?我从查询中删除了fpa.schenario_id=1,很抱歉造成误导,请参阅下面的may query
;WITH SUMCTE
AS
(
SELECT fpa.facility_id,
fpa.mp_surrogate_id,
fpa.process_id,
SUM(fpa.raw_amount) AS total_amount
FROM #tempAmount fpa
GROUP BY fpa.facility_id, fpa.mp_surrogate_id, fpa.process_id
)
SELECT CAST(1 as BIGINT) AS Scenario_id,
facility_id,
cge.CostGroupId result_total_id,
mp_surrogate_id,
CAST((SCT.total_amount * cge.CostSign) AS DECIMAL(25, 13)) result_total_amount
INTO ADM_FactProfitTotalAmount_1
FROM ResultTest cge
JOIN SUMCTE SCT ON cge.CostId = SCT.process_id