SQL Server查询运行速度很慢

时间:2013-05-01 19:08:37

标签: sql sql-server sql-server-2008

我通过SQL Server Management Studio执行的以下查询非常缓慢。

输入表tbl_sb12_bhs有大约40000条记录,一小时后只处理40条记录。

这里可以改变什么来使这个运行更快一点?

DECLARE @bsrange INT

SET @bsrange = 0

WHILE @bsrange <= (SELECT max([p_a_l_out])
                   FROM   [DB001].[FD\f7].[tbl_sb12_bhs])
  BEGIN
      INSERT INTO [FD\f7].tbl_sb13_b_lin1
                  (aId,
                   p_a_l_out,
                   bs_id,
                   bs_db,
                   bs_tbl,
                   bs_column,
                   Int1,
                   cd1,
                   Hop1,
                   Int2,
                   cd2,
                   Hop2,
                   Int3,
                   cd3,
                   Hop3,
                   Int4,
                   cd4,
                   Hop4,
                   Int5,
                   cd5,
                   Hop5,
                   Int6,
                   cd6,
                   Hop6,
                   Int7,
                   cd7,
                   Hop7,
                   Int8,
                   cd8,
                   Hop8,
                   Int9,
                   cd9,
                   Hop9,
                   Int10,
                   cd10,
                   Hop10,
                   Int11,
                   cd11,
                   Hop11,
                   Int12,
                   cd12,
                   Hop12,
                   Int13,
                   cd13,
                   Hop13,
                   Int14,
                   cd14,
                   Hop14,
                   Int15,
                   cd15,
                   Hop15,
                   Int16,
                   cd16,
                   Hop16)
      SELECT DISTINCT tbl_sb12_bhs.aId,
                      tbl_sb12_bhs.p_a_l_out,
                      tbl_sb12_bhs.bs_id,
                      tbl_sb12_bhs.bs_db,
                      tbl_sb12_bhs.bs_tbl,
                      tbl_sb12_bhs.bs_column,
                      tbl_rpt_val_pt_crl.pt_el_Int    AS Int1,
                      tbl_rpt_val_pt_crl.user_cd      AS cd1,
                      tbl_rpt_val_pt_crl.cfk_upel     AS Hop1,
                      tbl_rpt_val_pt_crl_1.pt_el_Int  AS Int2,
                      tbl_rpt_val_pt_crl_1.user_cd    AS cd2,
                      tbl_rpt_val_pt_crl_1.cfk_upel   AS Hop2,
                      tbl_rpt_val_pt_crl_2.pt_el_Int  AS Int3,
                      tbl_rpt_val_pt_crl_2.user_cd    AS cd3,
                      tbl_rpt_val_pt_crl_2.cfk_upel   AS Hop3,
                      tbl_rpt_val_pt_crl_3.pt_el_Int  AS Int4,
                      tbl_rpt_val_pt_crl_3.user_cd    AS cd4,
                      tbl_rpt_val_pt_crl_3.cfk_upel   AS Hop4,
                      tbl_rpt_val_pt_crl_4.pt_el_Int  AS Int5,
                      tbl_rpt_val_pt_crl_4.user_cd    AS cd5,
                      tbl_rpt_val_pt_crl_4.cfk_upel   AS Hop5,
                      tbl_rpt_val_pt_crl_5.pt_el_Int  AS Int6,
                      tbl_rpt_val_pt_crl_5.user_cd    AS cd6,
                      tbl_rpt_val_pt_crl_5.cfk_upel   AS Hop6,
                      tbl_rpt_val_pt_crl_6.pt_el_Int  AS Int7,
                      tbl_rpt_val_pt_crl_6.user_cd    AS cd7,
                      tbl_rpt_val_pt_crl_6.cfk_upel   AS Hop7,
                      tbl_rpt_val_pt_crl_7.pt_el_Int  AS Int8,
                      tbl_rpt_val_pt_crl_7.user_cd    AS cd8,
                      tbl_rpt_val_pt_crl_7.cfk_upel   AS Hop8,
                      tbl_rpt_val_pt_crl_8.pt_el_Int  AS Int9,
                      tbl_rpt_val_pt_crl_8.user_cd    AS cd9,
                      tbl_rpt_val_pt_crl_8.cfk_upel   AS Hop9,
                      tbl_rpt_val_pt_crl_9.pt_el_Int  AS Int10,
                      tbl_rpt_val_pt_crl_9.user_cd    AS cd10,
                      tbl_rpt_val_pt_crl_9.cfk_upel   AS Hop10,
                      tbl_rpt_val_pt_crl_10.pt_el_Int AS Int11,
                      tbl_rpt_val_pt_crl_10.user_cd   AS cd11,
                      tbl_rpt_val_pt_crl_10.cfk_upel  AS Hop11,
                      tbl_rpt_val_pt_crl_11.pt_el_Int AS Int12,
                      tbl_rpt_val_pt_crl_11.user_cd   AS cd12,
                      tbl_rpt_val_pt_crl_11.cfk_upel  AS Hop12,
                      tbl_rpt_val_pt_crl_12.pt_el_Int AS Int13,
                      tbl_rpt_val_pt_crl_12.user_cd   AS cd13,
                      tbl_rpt_val_pt_crl_12.cfk_upel  AS Hop13,
                      tbl_rpt_val_pt_crl_13.pt_el_Int AS Int14,
                      tbl_rpt_val_pt_crl_13.user_cd   AS cd14,
                      tbl_rpt_val_pt_crl_13.cfk_upel  AS Hop14,
                      tbl_rpt_val_pt_crl_14.pt_el_Int AS Int15,
                      tbl_rpt_val_pt_crl_14.user_cd   AS cd15,
                      tbl_rpt_val_pt_crl_14.cfk_upel  AS Hop15,
                      tbl_rpt_val_pt_crl_15.pt_el_Int AS Int16,
                      tbl_rpt_val_pt_crl_15.user_cd   AS cd16,
                      tbl_rpt_val_pt_crl_15.cfk_upel  AS Hop16
      FROM   (SELECT DISTINCT pk_a AS aId,
                              p_a_l_out,
                              bs_id,
                              bs_db,
                              bs_tbl,
                              bs_column,
                              hop_pt_id_1,
                              hop_pt_id_2,
                              hop_pt_id_3,
                              hop_pt_id_4,
                              hop_pt_id_5,
                              hop_pt_id_6,
                              hop_pt_id_7,
                              hop_pt_id_8,
                              hop_pt_id_9,
                              hop_pt_id_10,
                              hop_pt_id_11,
                              hop_pt_id_12,
                              hop_pt_id_13,
                              hop_pt_id_14,
                              hop_pt_id_15,
                              hop_pt_id_16
              FROM   [FD\f7].tbl_sb12_bhs
              WHERE  [p_a_l_out] >= @bsrange
                     AND [p_a_l_out] < ( @bsrange + 1 )) AS tbl_sb12_bhs
             LEFT JOIN tbl_rpt_val_pt_crl
               ON tbl_sb12_bhs.hop_pt_id_1 = tbl_rpt_val_pt_crl.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_1
               ON tbl_sb12_bhs.hop_pt_id_2 = tbl_rpt_val_pt_crl_1.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_2
               ON tbl_sb12_bhs.hop_pt_id_3 = tbl_rpt_val_pt_crl_2.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_3
               ON tbl_sb12_bhs.hop_pt_id_4 = tbl_rpt_val_pt_crl_3.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_4
               ON tbl_sb12_bhs.hop_pt_id_5 = tbl_rpt_val_pt_crl_4.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_5
               ON tbl_sb12_bhs.hop_pt_id_6 = tbl_rpt_val_pt_crl_5.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_6
               ON tbl_sb12_bhs.hop_pt_id_7 = tbl_rpt_val_pt_crl_6.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_7
               ON tbl_sb12_bhs.hop_pt_id_8 = tbl_rpt_val_pt_crl_7.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_8
               ON tbl_sb12_bhs.hop_pt_id_9 = tbl_rpt_val_pt_crl_8.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_9
               ON tbl_sb12_bhs.hop_pt_id_10 = tbl_rpt_val_pt_crl_9.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_10
               ON tbl_sb12_bhs.hop_pt_id_11 = tbl_rpt_val_pt_crl_10.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_11
               ON tbl_sb12_bhs.hop_pt_id_12 = tbl_rpt_val_pt_crl_11.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_12
               ON tbl_sb12_bhs.hop_pt_id_13 = tbl_rpt_val_pt_crl_12.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_13
               ON tbl_sb12_bhs.hop_pt_id_14 = tbl_rpt_val_pt_crl_13.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_14
               ON tbl_sb12_bhs.hop_pt_id_15 = tbl_rpt_val_pt_crl_14.sk_el_pt
             LEFT JOIN tbl_rpt_val_pt_crl AS tbl_rpt_val_pt_crl_15
               ON tbl_sb12_bhs.hop_pt_id_16 = tbl_rpt_val_pt_crl_15.sk_el_pt

      SET @bsrange = @bsrange + 1
  END 

3 个答案:

答案 0 :(得分:0)

如果目标上有索引或索引,那么SQL将重新索引每一行。我将禁用目标表上的任何索引,然后在插入完成时重新编译它们。 Id批量插入inro范围(比方说)5k记录,这样任何阻塞都会减少,或者我会在结果中选择select和bcp来创建临时文件。因为你每次在一次记录插入之前做了那些可怕的左连接。 SQL只能不能优化大约7或8个左或右连接。我的猜测是,表中插入的索引很少或没有索引,这意味着每个连接都会扫描一个表,或者每插入一行就扫描17个表。对不起,但这个方法在每个阶段都是错误的。或者你可以让老板给你买一个约会中心....

答案 1 :(得分:0)

我最好的猜测是,它很慢,因为你一次性完成了许多密集的操作。没有任何样本数据很难,但我可以尝试提出一些建议。

根据你的说法,它只会在一小时后处理40条记录,这就是循环内部正在减慢你的速度。

SELECT DISTINCT并不便宜,因为它必须比较所有数据,而且你也要比较很多列。如果可以的话,如果将列数限制为不同选择所需的最小值,然后将其自身连接到原始表,则可能会更快地运行。它应该足够简单,可以单独测试其余部分,以确保获得相同的结果以及是否更快。

此外,您拥有的联盟越多,性能就越差......我们为正常化付出的代价。

无论如何,我会退后一步,尝试将其分解为最小的工作单元,然后你可以单独测试每一个,直到找到罪魁祸首。这样做,你可能会想到一个更好的方法来做到这一点。同样,如果没有任何样本数据,这对我来说很难帮助。

答案 2 :(得分:0)

您可能想要做的另一件事是最初将连接加入临时表,然后引用它。您不必每次都进行不同的连接或连接。只需为bsrange添加where子句。

所以它会是这样的:

Create temporary table with as much of the joins/distinct as you can.
while.....
   insert into [FD\f7].tbl_sb13_b_lin1
       select * from temptable where  [p_a_l_out] >= @bsrange
                     AND [p_a_l_out] < ( @bsrange + 1 )