2011-02-08 81 views
2

我有此查詢:DELETE FROM優化

DELETE FROM f 
     WHERE ft != 'f' 
     OR fs NOT IN ( SELECT fs 
          FROM f 
         GROUP BY fs 
         HAVING COUNT(fs) >1)

這是很好做的工作只不過它比我預期更多的時間。我說的是2.25秒,將約209,000個記錄下降到約187,000。我認爲這可以改進,我想知道如何。

查詢說明:

addr opcode   p1 p2 p3 p4     p5 comment  
---- ------------- ---- ---- ---- ----------------- -- ------------- 
0  Trace   0  0  0      00    
1  Goto   0  82 0      00    
2  Null   0  1  0      00    
3  String8  0  3  0  f     00    
4  OpenRead  0  2  0  4     00    
5  Rewind   0  69 0      00    
6  Column   0  2  4      00    
7  Ne    3  66 4  collseq(BINARY) 63    
8  If    7  53 0      00    
9  Integer  1  7  0      00    
10 Null   0  6  0      00    
11 OpenEphemeral 4  1  0  keyinfo(1,BINARY) 00    
12 OpenEphemeral 5  2  0  keyinfo(1,BINARY) 00    
13 Integer  0  11 0      00    
14 Integer  0  10 0      00    
15 Gosub   13 50 0      00    
16 OpenRead  2  2  0  4     00    
17 Rewind   2  23 0      00    
18 Column   2  3  16      00    
19 Sequence  5  17 0      00    
20 MakeRecord  16 2  4      00    
21 IdxInsert  5  4  0      00    
22 Next   2  18 0      01    
23 Close   2  0  0      00    
24 Sort   5  53 0      00    
25 Column   5  0  15      00    
26 Compare  14 15 1  keyinfo(1,BINARY) 00    
27 Jump   28 32 28      00    
28 Move   15 14 1      00    
29 Gosub   12 41 0      00    
30 IfPos   11 53 0      00    
31 Gosub   13 50 0      00    
32 Column   5  0  16      00    
33 AggStep  0  16 9  count(1)   01    
34 Column   5  0  8      00    
35 Integer  1  10 0      00    
36 Next   5  25 0      00    
37 Gosub   12 41 0      00    
38 Goto   0  53 0      00    
39 Integer  1  11 0      00    
40 Return   12 0  0      00    
41 IfPos   10 43 0      00    
42 Return   12 0  0      00    
43 AggFinal  9  1  0  count(1)   00    
44 Integer  1  4  0      00    
45 Le    4  42 9      6a    
46 SCopy   8  18 0      00    
47 MakeRecord  18 1  4  c     00    
48 IdxInsert  4  4  0      00    
49 Return   12 0  0      00    
50 Null   0  8  0      00    
51 Null   0  9  0      00    
52 Return   13 0  0      00    
53 Column   0  3  4      00    
54 NotNull  4  57 0      00    
55 Rewind   4  66 0      00    
56 Goto   0  68 0      00    
57 Affinity  4  1  0  c     00    
58 Found   4  65 4  1     00    
59 NotNull  6  63 0      00    
60 Found   4  62 6  1     00    
61 Integer  -1 6  0      00    
62 AddImm   6  1  0      00    
63 If    6  68 0      00    
64 Goto   0  66 0      00    
65 Goto   0  68 0      00    
66 Rowid   0  2  0      00    
67 RowSetAdd  1  2  0      00    
68 Next   0  6  0      01    
69 Close   0  0  0      00    
70 OpenWrite  0  2  0  4     00    
71 OpenWrite  1  3  0  keyinfo(1,BINARY) 00    
72 RowSetRead  1  79 2      00    
73 NotExists  0  78 2      00    
74 Rowid   0  20 0      00    
75 Column   0  1  19      00    
76 IdxDelete  1  19 2      00    
77 Delete   0  1  0  f     00    
78 Goto   0  72 0      00    
79 Close   1  3  0      00    
80 Close   0  0  0      00    
81 Halt   0  0  0      00    
82 Transaction 0  1  0      00    
83 VerifyCookie 0  2  0      00    
84 TableLock  0  2  1  f     00    
85 Goto   0  2  0      00   

表定義(沒有索引還):

CREATE TABLE f (fi INTEGER PRIMARY KEY AUTOINCREMENT, 
       fn STRING, 
       ft STRING, 
       fs INTEGER)
+1

表定義?已定義的索引?不完整的問題會得到不完整的答案。 – 2011-02-08 03:06:05

+0

對不起,我忘了。我編輯了這個問題。 :) – 2011-02-08 03:15:53

+1

值得研究的另一件事是查詢的EXPLAIN,以便查詢優化器告訴你它在查詢中的作用。如果它做的事情已經非常聰明和快速,沒有理由進一步優化。 – 2011-02-08 03:16:04

回答

4

我不知道那兩秒一個 「殺手鐗」 查詢(雖然這一點,當然,取決於你的情況和需求)但有一點你可以測試是將查詢分成兩部分的效果。

這是因爲它當前會刪除符合任一條件的記錄,所以它很容易轉換爲兩個delete語句(如果要確保它是原子的,則在事務中)。你可以嘗試:

DELETE FROM f WHERE ft != 'f'; 
DELETE FROM f WHERE fs NOT IN (
    SELECT fs FROM f 
    GROUP BY fs 
    HAVING COUNT(fs) >1); 

看看是否改善了事情。它可能會或可能不會,這取決於您的數據庫管理系統和數據組成。它很可能會擺脫交叉記錄(那些滿足這兩個條件的記錄)在最可能更快的第一個查詢中。

但是,與所有的數據庫優化一樣,的措施,不要猜測!

然後,您可以重新組合並重新評估,或者集中精力加速第二個較簡單的查詢,如果它仍然存在問題。

特別是的一件事確保:在ftfs列上都有索引。如果你還沒有它們,這應該會加快你的查詢速度。

1

嘗試此查詢

DELETE FROM f 
WHERE ft <> 'f' 
    OR NOT EXISTS (Select * from f f2 
     WHERE f2.fs=f.fs and f2.id <> f.id) 

指標

on ft ; single-column 
on (fs, id) ; composite, in that order 
1
DELETE f 
FROM (
     SELECT fs 
     FROM f  
     GROUP BY fs  
     HAVING COUNT(fs) <=1 
    ) s 
WHERE (f.ft != 'f' OR f.fs = s.fs) 
相關問題