我有一个系统,用户可以查看他们单独订阅的类别,以及默认情况下他们所属区域中可用的类别。
所以,表格如下: 分类 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行)。我的设计在这里有问题吗?
如何在一个查询中同时检索用户的各个类别及其区域内的类别,而不需要花费多长时间?
谢谢!
答案 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已经指出的那样,你应该考虑索引你的数据。