【问题标题】:Will non-textual search benefit from search engine?非文本搜索会从搜索引擎中受益吗?
【发布时间】:2013-07-20 12:09:36
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: mysql search lucene sphinx faceted-search


    【解决方案1】:

    你为什么要在同一个 id 上加入 B 表 3 次?一个join就可以达到同样的效果:

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

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

    【讨论】:

    • 如果我只加入tableB 一次,那么B.value 应该同时出现在所有3 个列表中。 (不应该吗?)。如果我多次加入它,那么我可以分别从第一个列表和第二个列表等中过滤 A 以获得 B.values。我错了吗?正如我所说,它似乎有效。我确实有ix_tableb_value 索引。
    • 我没有在同一列上进行过滤。如果我有来自 B 的 A (1,2,3) 值中的某行,那么加入 B 3 次会给我 [(1,1,1), (1,1,2), (1,1,3 ),(1,2,1),..,(3,3,3)] 然后我可以找到 B1.value=1, B2.value=2, B3.value=3 的 A。对吗?
    • 使用 group by 得到相同的结果,但执行时间要长约 2 倍。无论如何,感谢您的尝试。
    • @zaquest 。 . .如果删除“A”表(以及order by 并将group by 更改为tablea_id),使用group by 进行查询需要多长时间?
    • 从我的问题中查询需要 4-5s;从你的回答 9-10s; group by 没有 order by 并且没有 A 需要 5-6 秒。如果我删除 SQL_CALC_FOUND_ROWSorder by 他们都会立即返回答案(0.00s)
    猜你喜欢
    • 1970-01-01
    • 2012-01-31
    • 2013-07-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 2016-06-09
    相关资源
    最近更新 更多