我有一个搜索网站。运行MySQL数据库。我想知道它是否会从搜索引擎(Sphinx,Lucene等)的性能中受益?怎么样,如果会的话?我可以使用分面搜索吗?我知道如果有文本搜索会有好处。但是如果大多数查询都像下面那样可能会有好处。
select SQL_CALC_FOUND_ROWS distinct tableA.id
from tableA as A
join tableB as B1 on A.id=B1.tablea_id
join tableB as B2 on A.id=B2.tablea_id
join tableB as B3 on A.id=B3.tablea_id
where
B1.value in ([list of ints here])
and
B2.value in ([another list of ints here])
and
B2.value in ([one more list of ints here])
order by ~A.updated_at
limit <from>,<amount>;
我们的想法是在tableA
中查找第一个列表中tableB
的值,然后过滤然后从第二个列表中留下tableB
中的值,等等。 ,计算所有发现和限制。
tableA
和tableB
是这样的:
create table tableA (
id int(11) not null autoincrement,
...
updated_at timestamp not null,
primary key (`id`),
key `ix_tablea_updated_at` (`updated_at`)
) engine=InnoDB;
create table tableB (
tablea_id int(11) not null,
value int(11) not null,
key `ix_tableb_tablea_id` (`tablea_id`),
key `ix_tableb_value` (`value`)
) engine=InnoDB;
tableA
包含~20万行。 tableB
包含~1.2M行。 B.value in ([list of ints])
的数量因查询而异,lists of ints
也是如此。
如果我无法从搜索引擎中受益,我可以通过其他方式提高性能吗?
据我所知,问题是order by ~A.updated_at
并计算找到的行。有没有办法加快使用MySQL本身的排序和计数?
PS。请原谅我的英语。希望你能理解我。
答案 0 :(得分:2)
为什么你在同一身份证上加入B表三次?您可以通过一个联接获得相同的效果:
select SQL_CALC_FOUND_ROWS distinct tableA.id
from tableA A join
tableB B
on A.id = B.tablea_id
where B.value in ([list of ints here]) and
B.value in ([another list of ints here]) and
B.value in ([one more list of ints here])
order by A.updated_at
limit <from>, <amount>;
有三个列表是多余的,所以你也可以这样做:
select SQL_CALC_FOUND_ROWS distinct tableA.id
from tableA A join
tableB B
on A.id = B.tablea_id
where B.value in ([big big combined list of ints here])
order by A.updated_at
limit <from>, <amount>;
如果您的索引位于B(value)
甚至B(value, tablea_id)
,那么效果会更好。
编辑:
不,您的查询无法按照您的想法运作。每次加入be表时,都会将行数相乘。比如说,A表中的值QQQ在B表中有10个对应的行。第一个连接获得10行,第二个连接将其乘以100,第三个连接为1,000。这可能是您性能问题的根源。
您只是对同一列进行连续过滤。实际上,我怀疑你真的想知道三个列表中每个列表中都存在B id的所有As。如果是这样,那么这是一个“set-within-sets”查询,并使用group by
轻松完成:
select SQL_CALC_FOUND_ROWS tableA.id
from tableA A join
tableB B
on A.id = B.tablea_id
group by tableA.id
having sum(B.value in ([list of ints here])) > 0 and
sum(B.value in ([another list of ints here])) > 0 and
sum(B.value in ([one more list of ints here])) > 0
order by A.updated_at
limit <from>, <amount>;
您的原始方法可能确实有效 - 这很有趣。它通常效率很低(除非其中一个值永远不会出现在数据中,因此连接最终不会返回任何行)。