2013-07-09 121 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