2013-07-09 4 views
0

Мне пришлось создать запрос sql, который получает всех пользователей с именем, именем или фамилией, которая содержит символ '|'. Так что я сделал что-то вроде:Sql Query слишком медленный

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 '%|%' 

Этого запрос большого в тестовой среде работает около тысячи профилей, но раз в производственной среде, которая содержит сотни тысяч профилей, если не близко к миллиону.

Мы бежим 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 
Смежные вопросы