10

我有一个 webapp 开发问题,我已经开发了一个解决方案,但我正在尝试寻找其他想法来解决我看到的一些性能问题。

问题陈述:

  • 用户输入几个关键字/标记
  • 应用程序搜索令牌的匹配项
  • 每个令牌需要一个结果
    • 即,如果一个条目有 3 个令牌,我需要 3 次条目 ID
  • 对结果进行排名
    • 为令牌匹配分配 X 点
    • 根据点对条目 ID 进行排序
    • 如果点值相同,则使用日期对结果进行排序

我想要做的,但还没有想出的是,发送 1 个查询,该查询返回类似于 in() 的结果,但为检查的每个条目 id 的每个令牌匹配返回一个重复的条目 id。

有没有比我正在做的更好的方法来做到这一点,即使用多个单独的查询,每个令牌运行一个查询?如果是这样,实现这些的最简单方法是什么?

编辑
我已经对条目进行了标记,例如,“see spot run”的条目 id 为 1,三个标记“see”、“spot”、“run”,它们位于单独的标记表中,具有与它们相关的条目 ID,因此表可能如下所示:

'see', 1 
'spot', 1 
'run', 1 
'run', 2 
'spot', 3 
4

4 回答 4

6

您可以在 MySQL 中使用“UNION ALL”在一个查询中实现这一点。

只需遍历 PHP 中的标记,为每个标记创建一个 UNION ALL:

例如,如果标记是“x”、“y”和“z”,您的查询可能看起来像这样

SELECT * FROM `entries` 
WHERE token like "%x%" union all 
    SELECT * FROM `entries` 
    WHERE token like "%y%" union all 
        SELECT * FROM `entries` 
        WHERE token like "%z%" ORDER BY score ect...

order 子句应该对整个结果集进行操作,这正是您所需要的。

就性能而言,它不会那么快(我猜),但是对于数据库,速度方面的主要开销通常是从 PHP 向数据库引擎发送查询并接收结果。使用这种技术,这只发生一次,而不是每个令牌一次,因此性能会提高,我只是不知道这是否足够。

于 2008-09-06T20:12:44.307 回答
3

我知道这不是您所问问题的严格答案,但如果您的表是数千行而不是数百万行,那么 FULLTEXT 解决方案可能是最好的方法。

在 MySQL 中,当您在索引列上使用 MATCH 时,您提供的每个关键字都会被赋予一个相关性分数(大致由每个关键字被提及的次数计算),这将比您的方法更准确,并且对于多个关键字当然更有效。

见这里: http ://dev.mysql.com/doc/refman/5.0/en/fulltext-search.html

于 2008-09-08T09:48:00.363 回答
1

如果您使用的是 UNION ALL 模式,您可能还希望在查询中包含以下部分:

SELECT COUNT(*) AS C
...
GROUP BY ID
ORDER BY c DESC

虽然这是一个非常简单的示例,但它确实可以让您了解每个结果的匹配频率,这可能是一个伪排名。

于 2008-09-06T21:25:51.417 回答
-1

如果您使用为搜索任务而不是数据库设计的数据结构,您可能会获得更好的性能。例如,您可能会尝试查看构建倒排索引。然而,与其自己编写它,您可能还想研究像Lucene这样的东西,它可以为您完成大部分工作。

于 2008-09-08T08:17:06.023 回答