Как я могу сделать этот запрос SQL более эффективным? PHP - PullRequest
3 голосов
/ 23 марта 2010

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

Итак, таблицы таковы: категории UsersCategories RegionsCategories

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

Мой запрос выглядит следующим образом:

        Select * FROM (categories c)
        LEFT JOIN users_categories uc on uc.category_id = c.id
        LEFT JOIN regions_categories rc on rc.category_id = c.id
        WHERE (rc.region_id = ? OR uc.user_id = ?)

По крайней мере, я считаю, что это запрос, я создаю его, используя слой ORM в Cake, поэтому точный:

        $conditions = array(
                             array( "OR" => array (
                                'RegionsCategories.region_id' => $region_id,
                                'UsersCategories.user_id' => $user_id
                             )
        ));
        $this->find('all', $conditions);

Это оказывается невероятно медленным (иногда около 20 секунд или около того. Каждая таблица имеет около 5000 строк). Мой дизайн виноват здесь?

Как я могу получить как отдельные категории пользователей, так и категории в своем регионе, все в одном запросе, без возрастов?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 23 марта 2010

Убедитесь, что все столбцы Categories.id, users_categories.category_id, users_categories.user_id, region_categories.category_id и region_categories.region_id проиндексированы.

1 голос
/ 23 марта 2010

Попробуйте это:

select * from
(
 select category_id from users_categories where user_id = ?
 union
 select category_id from region_categories where region_id = ?
) as q
inner join categories c on c.id = q.category_id

Полагаю, он выполняет ту же работу, но не использует ИЛИ (чего следует избегать в большинстве СУБД), что позволяет серверу более эффективно использовать индексы. Конечно, как уже отмечал jmans, вам следует подумать об индексации своих данных.

1 голос
/ 23 марта 2010

Предположим, что предложения jmans уже реализованы;

Запросы IIRC MySQL могут использовать только один индекс за раз, и, следовательно, OR может быть дорогостоящим и быстрее разделить его на два запроса и объединить их, позволяя каждому подзапросу использовать свой индекс

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