1

我有一个带有搜索功能的网站。运行 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包含约 200k 行。tableB包含约 120 万行。数量B.value in ([list of ints])因查询而异,如lists of ints.

如果我无法从搜索引擎中受益,我可以通过任何其他方式提高性能吗?

据我所知,问题在于order by ~A.updated_at计算找到的行。有没有办法使用 MySQL 本身加速排序和计数?

PS。原谅我的英语。希望你能理解我。

4

1 回答 1

2

你为什么要在同一个 id 上加入 B 表 3 次?您可以通过一次连接获得相同的效果:

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。这可能是您的性能问题的根源。

您只是在同一列上进行连续过滤。实际上,我怀疑您真的想知道所有 As,三个列表中的每个列表中都有一个 B id。如果是这样,那么这是一个“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>;

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

于 2013-07-21T19:36:53.900 回答