【问题标题】:Speed up SQL Server 2008 Insert Into Query加快 SQL Server 2008 插入查询
【发布时间】:2013-10-17 11:05:32
【问题描述】:

以下插入查询需要 7 秒才能运行,并且由于它在循环中运行多次,所以时间加起来。我需要帮助来加快速度,90% 的成本用于聚集索引插入,10% 用于 FN_qryPSLA() 的表扫描。

INSERT INTO tblTPS (fldPK, fldDTA, fldCI, fldMN, fldMDN, fldIQ, fldSD, fldNDS, fldNIN, fldNL, fldMin, fldMax, fldUNC, fldAVA, fldBA)
SELECT fldPK, fldDTA, fldCI, fldMN, fldMDN, fldIQ, fldSD, fldNDS, fldNIN, fldNL, fldMin, fldMax, fldUNC, fldAVA, 1 AS fldBA
FROM FN_qryPSLA()
WHERE (((fldPK)= 37923 ) AND ((fldMN)<>-254));

下面是FN_qryPSLA()... Distinct Sort 的成本是 85%(如果去掉,成本是 80% Hash Match (Aggregate))

FUNCTION [dbo].[FN_qryPSLA](@PK INT)
RETURNS @tmpTblPSLA TABLE (
fldPK       BIGINT      NOT NULL,           
fldDTA          DATETIME    NULL,
fldCI       FLOAT       NULL,   
fldMN       FLOAT       NULL,
fldMDN      FLOAT       NULL,
fldIQ       FLOAT       NULL,               
fldSD       FLOAT       NULL,
fldNDS      BIGINT      NULL,
fldNIN      BIGINT      NULL,
fldNL       BIGINT      NULL,
fldMin      FLOAT       NULL,
fldMax      FLOAT       NULL,
fldUNC      VARCHAR(5)  NULL, 
fldAVA      TINYINT     NULL
) 
AS
BEGIN 
WITH gDPS AS 
(SELECT fldPK, Max(fldDTA) AS fldDTA
FROM tblAPS
GROUP BY fldPK)

    SELECT fldPK, fldDTA, fldCI, fldMN, fldMDN, fldIQ, fldSD, fldNDS, fldNIN, fldNL, fldMin, fldMax, fldUNC, fldAVA
FROM tblAPS INNER JOIN getDPS ON (tblAPS.fldDTA = gDPS.fldDTA) AND (tblAPS.fldPK = gDPS.fldPK)
    GROUP BY fldPK, fldDTA, fldCI, fldMN, fldMDN, fldIQ, fldSD, fldNDS, fldNIN, fldNL, fldMin, fldMax, fldUNC, fldAVA
    HAVING tblAPS.fldMN<>-254
    ORDER BY tblAPS.fldPK, tblAPS.fldCI;
    RETURN; 
END;

涉及的字段(正在查询的表中的 200 万条记录)fldPSD 上的聚集索引...

fldPK           BIGINT      NOT NULL,           
fldDTA  DATETIME    NULL,
fldCI       FLOAT       NULL,   
fldMN           FLOAT       NULL,
fldMDN          FLOAT       NULL,
fldIQ               FLOAT       NULL,               
fldSD               FLOAT       NULL,
fldNDS      BIGINT      NULL,
fldNIN          BIGINT      NULL,
fldNL           BIGINT      NULL,
fldMin              FLOAT       NULL,
fldMax              FLOAT       NULL,
fldUNC      VARCHAR(5)  NULL, 
fldAVA      TINYINT     NULL

【问题讨论】:

  • 向我们展示FN_qryPSLA()完整定义。您保留了定义的标头,这恰好对于此类性能问题非常重要。
  • @RBarryYoung 我编辑了帖子以包含其余功能。
  • 我最终得到了建议这个索引的 SQL...CREATE NONCLUSTERED INDEX [$fldPKMdnInd] ON [dbo].[tblAPS] ([fldPK],[fldMDN]) INCLUDE ([fldDTA],[ fldCI],[fldMDN],[fldIQ],[fldSD],[fldNDS],[fldNIN],[fldNL],[fldMin],[fldMax],[fldUNC],[fldAVA]) 去
  • 这是我要查看的内容:“以下插入查询需要 7 秒才能运行,并且由于它在循环中运行多次,因此时间会增加。 " 循环在 SQL 中不是可取的东西,因为它们是查询/集合的解构部分,通常可以更快更简单。

标签: sql-server-2008 stored-procedures


【解决方案1】:

这个sn-p对我来说很突出:

90% 的成本用于聚集索引插入

考虑到这一点,我可以想到两件事来尝试:

  1. 更改目标表的Fill Factor 以在每页中为传入数据留出一些空白空间。
    或者:
  2. 在插入前对数据进行排序,使其与主键顺序匹配。

这两者的目标都是减少在插入期间重新分页数据和索引的需要。

在第一种情况下,您在创建时在每个页面中保留空白空间,这样当您插入记录时,您不需要经常拆分或创建新页面。

在第二种情况下,您不能将 ORDER BY 与作为插入的一部分的 SELECT 命令一起使用...但是您可以通过该 SELECT 命令中的表上的索引来影响顺序。目标是通过按顺序提供数据,您将在插入数据时按顺序一次处理一页,而不是四处跳动并可能需要一遍又一遍地重建同一页面。

【讨论】:

  • 目标表实际上只保存临时数据,而不是很多,所以我决定删除索引。现在成本是 75% 插入 tblTPS,有没有办法降低这个成本?
  • 不,你不会想要的。请记住,您在这里看到的是百分比:这个数字总是必须加起来为 100。您在那里看到的是原始插入性能:实际插入数据。 75%还不错。您现在可以做的是获得更多内存或更快的磁盘,或者减少另外 25%。
  • 另外 25% 用于扫描子查询,子查询有 85% 用于不同的排序,但那时我真的可能只会挤出毫秒。
  • 我只是将 fldPK 条件放入子查询中,并将其缩短到至少 2 秒
  • @MacGyver 你不能保证顺序,但你可以通过使用索引来强烈影响它
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多