非文本搜索会从搜索引擎中受益吗?

时间:2013-07-21 19:29:27

标签: mysql search lucene sphinx faceted-search

我有一个搜索网站。运行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中的值,等等。 ,计算所有发现和限制。

tableAtableB是这样的:

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。请原谅我的英语。希望你能理解我。

1 个答案:

答案 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>;

您的原始方法可能确实有效 - 这很有趣。它通常效率很低(除非其中一个值永远不会出现在数据中,因此连接最终不会返回任何行)。