2013-07-09 226 views
0

我不得不創建一個sql查詢來獲取所有包含字符'|'的名字,中間名或姓氏的用戶。所以,我不喜歡的東西:Sql查詢太慢

SELECT two.id, 
     two.username, 
     one.firstname, 
     one.middlename, 
     one.lastname 
FROM table_one one INNER JOIN table_two two ON two.id = one.id 
WHERE one.firstname LIKE '%|%' 
OR one.middlename LIKE '%|%' 
OR one.lastname LIKE '%|%' 

該查詢工作在測試環境中偉大的大約一千配置文件,但它超時的生產環境,其中包含數千型材幾百,如果不是接近100萬人次。

我們正在運行DB2 8.2版本

+3

使用' '%|%''使得指標無用。 –

+0

嘗試使用索引.... –

+0

爲什麼你要尋找'|'? –

回答

2

你可以嘗試分裂搜索以卸下OR,這是臭名昭著的表現不佳:

SELECT 
    two.id, 
    two.username, 
    one.firstname, 
    one.middlename, 
    one.lastname 
FROM (
    SELECT id, firstname, middlename, lastname 
    FROM table_one 
    WHERE one.firstname LIKE '%|%' 
    UNION 
    SELECT id, firstname, middlename, lastname 
    FROM table_one 
    WHERE one.middlename LIKE '%|%' 
    UNION 
    SELECT id, firstname, middlename, lastname 
    FROM table_one 
    WHERE one.lastname LIKE '%|%' 
) one 
INNER JOIN table_two two ON two.id = one.id 

隨着指數在每個名字列,有一個機會每個將用於單獨的聯合查詢。

UNION上的使用方便地丟棄重複項,所以多個名稱列中包含一個管道字符的情況不會導致重複輸出。

+0

使用POSITION()代替LIKE怎麼樣?我不覺得在任何情況下都使用索引,但POSITION()似乎快一點,然後模式匹配。 –

+0

@DavidJashi它可能是,但我同意這是一個渺茫的機會。我可以看到,優化器*可能*選擇掃描索引而不是表格頁面,因爲索引中的每個頁面中的條目比表格中的更多,所以應該對掃描有利,因此「使用」索引,但即使如此,它可能不會更快。我認爲沒有一個重要的方法來解決糟糕的表現。 – Bohemian

0

嘗試

SELECT two.id, 
     two.username, 
     one.firstname, 
     one.middlename, 
     one.lastname 
FROM table_one one INNER JOIN table_two two ON two.id = one.id 
WHERE POSITION('|',concat(one.firstname,one.middlename,one.lastname),OCTETS)>0 

SELECT two.id, 
     two.username, 
     one.firstname, 
     one.middlename, 
     one.lastname 
FROM table_one one INNER JOIN table_two two ON two.id = one.id 
WHERE POSITION('|',one.firstname,OCTETS)+POSITION('|',one.middlename,OCTETS)+POSITION('|',one.lastname),OCTETS)>0