MySQL - лучший способ сделать этот запрос? - PullRequest
1 голос
/ 08 сентября 2010

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

Любой совет?

ОБНОВЛЕНО - это может быть 'что-то% ':

SELECT a.`object_id`, a.`type`, 
    IF( b.`name` IS NOT NULL, b.`name`,
        IF( c.`name` IS NOT NULL, c.`name`, 
            IF( d.`name` IS NOT NULL, d.`name`,
                IF ( e.`name` IS NOT NULL, e.`name`, f.`name` )
            )
        )
    ) AS name
FROM `user_permissions` AS a 
   LEFT JOIN `divisions` AS b 
       ON ( a.`object_id` = b.`division_id` 
           AND a.`type` = 'division' 
           AND b.`status` = 1 ) 
   LEFT JOIN `departments` AS c 
       ON ( a.`object_id` = c.`department_id` 
           AND a.`type` = 'department'  
           AND c.`status` = 1 ) 
   LEFT JOIN `sections` AS d 
       ON ( a.`object_id` = d.`section_id` 
           AND a.`type` = 'section'  
           AND d.`status` = 1 ) 
   LEFT JOIN `units` AS e 
       ON ( a.`object_id` = e.`unit_id` 
           AND a.`type` = 'unit'  
           AND e.`status` = 1 ) 
   LEFT JOIN `positions` AS f 
       ON ( a.`object_id` = f.`position_id` 
           AND a.`type` = 'position'  
           AND f.`status` = 1 ) 
WHERE a.`user_id` = 1 AND ( 
    b.`name` LIKE '?%' OR
    c.`name` LIKE '?%' OR
    d.`name` LIKE '?%' OR
    e.`name` LIKE '?%' OR
    f.`name` LIKE '?%'
)

Ответы [ 3 ]

3 голосов
/ 08 сентября 2010

Два простых, быстрых запроса часто лучше, чем один огромный, неэффективный запрос.

Вот как я бы это разработал:

Сначала создайте таблицу для всех ваших имен в формате MyISAM с индексом FULLTEXT. Вот где хранятся ваши имена. Каждый из соответствующих типов объектов (например, отделы, подразделения и т. Д.) Являются зависимыми таблицами, первичный ключ которых ссылается на первичный ключ главной таблицы именованных объектов.

Теперь вы можете искать имена с помощью этого гораздо более простого запроса, который выполняется невероятно быстро:

SELECT a.`object_id`, a.`type`, n.name, n.object_type
FROM `user_permissions` AS a 
JOIN `named_objects` AS n ON a.`object_id = n.`object_id`
WHERE MATCH(n.name) AGAINST ('name-to-be-searched')

Использование полнотекстового индекса будет выполняться в сотнях раз быстрее, чем при использовании LIKE так, как вы делаете.

Если у вас есть идентификатор и тип объекта, если вам нужны какие-либо другие атрибуты соответствующего типа объекта, вы можете выполнить секундный SQL-запрос, присоединяющийся к таблице для соответствующего типа объекта:

SELECT ... FROM {$object_type} WHERE object_id = ?

Это также будет происходить очень быстро.


Ваш комментарий: Да, я бы создал таблицу с именами, даже если она избыточна.

1 голос
/ 08 сентября 2010

Кроме изменения вложенных Ifs для использования функции Coalesce () (MySql имеет Coalesce (), не так ли)?Вы можете сделать немногое, если вам нужно отфильтровать этот входной параметр с выражением like.Помещение фильтра в столбец с использованием выражения Like, где параметр Like имеет подстановочный знак в начале, как и вы, делает аргумент запроса невозможным для SARG, что означает, что обработчик запросов должен выполнить полное сканирование таблицы все строки в таблице для оценки предиката фильтра.

Он не может использовать индекс, потому что индекс основан на значениях столбца, и с вашим параметром Like он не знает, с каких записей индекса читать (так как параметр начинается с подстановочного знака)

если MySql имеет Coalesce, вы можете заменить свой Select на:

SELECT a.`object_id`, a.`type`,
Coalesce(n.name, c.name, d.Name, e.Name) name

Если вы можете заменить параметр аргумента поиска, чтобы он не начинался с символа подстановки, просто убедитесь, что естьиндекс для столбца имени в каждой из таблиц, и (если сейчас нет индексов в этом столбце), производительность запроса значительно возрастет.

1 голос
/ 08 сентября 2010

Есть 500 вещей, которые вы можете сделать. Оптимизируйте, когда вы знаете, где ваши узкие места. До этого времени работайте над тем, чтобы привлечь этих пользователей в свое приложение. Это гораздо более высокий приоритет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...