如何使此SQL查询更有效? PHP

时间:2010-03-23 20:25:04

标签: php sql cakephp

我有一个系统,用户可以查看他们单独订阅的类别,以及默认情况下他们所属区域中可用的类别。

所以,表格如下: 分类 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 = ?)

至少我相信这是查询,我使用Cake的ORM层创建它,所以确切的是:

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

结果非常缓慢(有时大约20秒左右。每张桌子大约有5000行)。我的设计在这里有问题吗?

如何在一个查询中同时检索用户的各个类别及其区域内的类别,而不需要花费多长时间?

谢谢!

3 个答案:

答案 0 :(得分:2)

确保将categories.id,users_categories.category_id,users_categories.user_id,regions_categories.category_id和regions_categories.region_id列全部编入索引。

答案 1 :(得分:1)

假设jmans的建议已经实施;

IIRC MySQL查询一次只能使用一个索引,因此OR可能很昂贵,将它分成两个查询和UNION它们会更快,允许每个子查询使用不同的索引

答案 2 :(得分:1)

试试这个:

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

我猜它做同样的工作,但不使用OR(这是大多数RDBMS要避免的事情) - 因此让服务器以更有效的方式使用索引。原因,正如jmans已经指出的那样,你应该考虑索引你的数据。