Informix上的SQL语句性能问题

时间:2011-02-22 11:02:09

标签: sql optimization query-optimization informix

我有这个需要很长时间才能运行的Informix SQL语句。有没有人看到任何方法来优化它,所以它不会花这么长时间?

SELECT * FROM OriginalTable WHERE type = 'S' AND flag <> 'S' INTO TEMP TempTableA;

SELECT * FROM OriginalTable WHERE type = 'Z' AND flag <> 'S' INTO TEMP TempTableB;

UPDATE OriginalTable SET flag = 'D' WHERE Serialnumber in
(
select Serialnumber from TempTableA
WHERE NOT EXISTS(SELECT * FROM TempTableB
               WHERE TempTableB.Col1 = TempTableA.Col1
                 AND TempTableB.Col2 = TempTableA.Col2)
) 

我的OriginalTable大约有3亿行,TempTableA 93K行和TempTableB 58K行。

3 个答案:

答案 0 :(得分:2)

Update OriginalTable 
Set flag = 'D' 
Where Type = 'S'
    And Flag <> 'S'
    And Not Exists  (
                    Select 1
                    From OriginalTable As T1
                    Where T1.Type = 'Z'
                        And T1.flag <> 'S'
                        And T1.Col1 = OriginalTable.Col1
                        And T1.Col2 = OriginalTable.Col2
                    )

答案 1 :(得分:0)

我太懒了,无法测试测试数据,但也许可以这样做?

SELECT col1, col2, 
CASE WHEN type = 'S' THEN 1 
ELSE WHEN type = 'Z' THEN 2 END AS filteredType 
FROM OriginalTable WHERE (type = 'S' OR type = 'Z') AND flag <> 'S' INTO TempTable;

UPDATE OriginalTable SET flag = 'D' WHERE Serialnumber IN
(
SELECT t1.Serialnumber FROM TempTable t1
LEFT JOIN TempTable t2 ON (t1.col1 = t2.col2 AND t1.col2 = t2.col2)
WHERE t1.filteredType = 1
AND t2.filteredType = 2 
AND t2.Serialnumber IS NULL
)

这样你可以省略一个加载到临时表中。另一方面,新列filterType上没有索引。

我也不知道informix。希望它无论如何都有帮助。

答案 2 :(得分:0)

采用与@tombom类似的方法。仅预先查询您关心的列以使临时表更小。如果您正在处理一个包含60列的表格,那么您填写的内容不仅仅是3-4列,而您的主要考虑因素是有效的序列号。预先测试查询以确保它为您提供了您期望的正确集合,然后将其应用于SQL更新。

所以在这里,内部查询是你不想要的...因为你只是在比较这个表中的第1列和第2列,所以我只是预先查询。我正在对COL1和COL2上的内部结果集进行LEFT JOIN。我知道,你想要排除在这个结果集中找到的...这就是为什么,在OUTER WHERE子句中,我添加了“AND ExcludeThese.Col1 IS NULL”。因此,OT1中从未存在于子查询中的任何实例都很好(通过左连接),而那些找到了,将在col1和col2上匹配,但是THOSE将通过“和”子句排除。我描述过。

SELECT OT1.SerialNumber
    FROM OriginalTable OT1
        LEFT JOIN ( select OT2.Col1,
                           OT2.Col2
                       FROM OriginalTable OT2
                       where OT2.type = 'Z' 
                         AND OT2.flag <> 'S' ) ExcludeThese
           ON OT1.Col1 = ExcludeThese.Col1
          AND OT1.Col2 = ExcludeThese.Col2
    WHERE  OT1.type = 'S' 
       AND OT1.flag <> 'S'
       AND ExcludeThese.Col1 IS NULL
    ORDER BY
       OT1.SerialNumber
    INTO 
       TEMP TempTableA;  

再次,单独测试此查询以确保您获得所需的记录。为了帮助澄清返回的记录,请更改上面的选择以包含更多列以进行心理/健全性检查,例如

SELECT OT1.SerialNumber,
       OT1.Col1,
       OT1.Col2,
       ExcludeThese.Col1 JoinedCol1,
       ExcludeThese.Col2 JoinedCol2
  from  <keep rest of query intact>

现在,您将能够看到这些列的序列号和实例是否会加入“excludeThese”结果集...请重试,但只删除 “AND ExcludeThese.Col1 IS NULL”子句,您将看到其他行以及为什么排除它们 - 即如果您对内容有任何疑问。

一旦您对预查询感到满意...它将只返回SerialNumber的单列,可以进行索引/优化,因为您要进入临时表,构建索引,然后应用您的更新。 / p>

UPDATE OriginalTable 
   SET flag = 'D' 
   WHERE Serialnumber in ( select Serialnumber from TempTableA  );