【问题标题】:MySQL/PHP Search EfficiencyMySQL/PHP 搜索效率
【发布时间】:2011-02-26 14:18:40
【问题描述】:

我正在尝试为我的网站创建一个小型搜索。我试过使用全文索引搜索,但我永远无法让它工作。这是我想出的:

if(isset($_GET['search'])) {

$search = str_replace('-', ' ', $_GET['search']);
$result = array();

$titles = mysql_query("SELECT title FROM Entries WHERE title LIKE '%$search%'");
while($row = mysql_fetch_assoc($titles)) {
    $result[] = $row['title'];
}

$tags = mysql_query("SELECT title FROM Entries WHERE tags LIKE '%$search%'");
while($row = mysql_fetch_assoc($tags)) {
    $result[] = $row['title'];
}

$text = mysql_query("SELECT title FROM Entries WHERE entry LIKE '%$search%'");
while($row = mysql_fetch_assoc($text)) {
    $result[] = $row['title'];
}

$result = array_unique($result);
}

所以基本上,它会搜索数据库中所有条目的所有标题、正文和标签。这工作得很好,但我只是想知道它的效率如何?这也仅适用于小型博客。无论哪种方式,我只是想知道这是否可以提高效率。

【问题讨论】:

    标签: php mysql search performance


    【解决方案1】:

    没有办法让LIKE '%pattern%' 查询高效。一旦您获得大量数据,使用这些通配符查询的执行速度比使用全文索引解决方案慢数百或数千倍。

    你应该看看我为 MySQL 大学做的演讲: http://www.slideshare.net/billkarwin/practical-full-text-search-with-my-sql

    下面是如何让它工作:

    1. 首先确保您的表使用 MyISAM 存储引擎。 MySQL FULLTEXT 索引仅支持 MyISAM 表。 (编辑 11/1/2012: MySQL 5.6 正在为 InnoDB 表引入 FULLTEXT 索引类型。)

      ALTER TABLE Entries ENGINE=MyISAM;
      
    2. 创建全文索引。

      CREATE FULLTEXT INDEX searchindex ON Entries(title, tags, entry);
      
    3. 搜索它!

      $search = mysql_real_escape_string($search);
      $titles = mysql_query("SELECT title FROM Entries 
          WHERE MATCH(title, tags, entry) AGAINST('$search')");
      while($row = mysql_fetch_assoc($titles)) {
          $result[] = $row['title'];
      }
      

      请注意,您在MATCH 子句中命名的列必须与您在全文索引定义中声明的列的顺序相同。否则将无法正常工作。


    我尝试过使用全文索引搜索,但始终无法使用它...我只是想知道这是否可以提高效率。

    这就像在说,“我不知道如何使用这把电锯,所以我决定用小刀砍掉这棵红木树。我怎样才能让它和电锯一样好用?”


    关于您关于搜索匹配超过 50% 行的单词的评论。

    MySQL 手册上写着this:

    需要绕过50%限制的用户可以使用布尔搜索模式;见Section 11.8.2, “Boolean Full-Text Searches”

    还有this:

    自然语言的 50% 门槛 搜索是由 选择的特定加权方案。到 禁用它,查找以下内容 storage/myisam/ftdefs.h 中的一行:

    #define GWS_IN_USE GWS_PROB

    将该行更改为:

    #define GWS_IN_USE GWS_FREQ

    然后重新编译 MySQL。没有必要 在这种情况下重建索引。

    此外,您可能正在搜索停用词。这些是全文搜索忽略的单词,因为它们太常见了。诸如“的”之类的词。见http://dev.mysql.com/doc/refman/5.1/en/fulltext-stopwords.html

    【讨论】:

    • 严格按照指示进行,但仍然没有成功。我输入了其中一个条目的标题,但没有返回。我在本地使用 MAMP 进行测试是否重要?
    • 好的,经过进一步测试,我得出了一些奇怪的结果:它永远不会返回某个帖子(因为在这个特定的帖子中,无论如何都不会返回)。在其他帖子中,它不适用于在条目内搜索文本,但在键入标题和标签时它可以工作。这有意义吗?
    • 啊哈!我发现了问题:当它匹配数据库中的每个(或超过一半)项目时,它不会返回任何内容。有什么办法吗?我想这实际上更有效和合乎逻辑,但我只是没想到。谢谢你的帮助!编辑:我希望它在您键入部分标题时匹配条目,这可能吗? (例如,搜索“新”会得到“新帖子”)
    • (另请注意 Bill 示例中的 mysql_real_escape_string。没有它,您当前的代码很容易受到 SQL 注入攻击。)
    • 哦!谢谢你的名单!在这种情况下,请忽略我之前评论的编辑部分。
    【解决方案2】:

    使用LIKE不是全文。

    您需要使用... WHERE MATCH(column) AGAINST('the query') 才能访问全文搜索。

    【讨论】:

    • 我意识到,我说我尝试了全文但永远无法让它工作,所以我自己编写了代码。
    • @iMaster - 哦。请注意,与使用全文相比,您的代码效率非常低...也许您应该尝试让它工作并解决该问题?
    【解决方案3】:

    MySQL 全文搜索有效——我会对其进行研究和调试,而不是尝试这样做。执行 3 个单独的 MySQL 查询不会有任何效率。

    如果您想提高效率,可以将LIKE 语句分隔在一个查询中,并在它们之间使用OR

    【讨论】:

      猜你喜欢
      • 2014-03-22
      • 2012-02-13
      • 2012-05-18
      • 1970-01-01
      • 2019-12-20
      • 1970-01-01
      • 2012-08-01
      • 2019-02-27
      • 2011-10-21
      相关资源
      最近更新 更多