【问题标题】:Most efficient way to search in SQL?在 SQL 中搜索最有效的方法是什么?
【发布时间】:2012-03-24 07:00:54
【问题描述】:

我有一个包含 75,000 多行的数据库,每天添加 500 多个条目。

每一行都有一个标题和描述。

我创建了一个 RSS 提要,它为您提供特定搜索词的最新条目(例如,http://site.com/rss.rss?q=Pizza 将输出搜索词“披萨”的 RSS)。

我想知道为此编写 SQL 查询的最佳方式是什么。现在我有:

SELECT * 
FROM 'table' 
WHERE (('title' LIKE %searcherm%) OR ('description' LIKE %searcherm%))
LIMIT 20;

但问题是执行查询需要 2 到 10 秒。

是否有更好的方法来编写查询,我是否必须缓存结果(我将如何做?)或者更改数据库结构中的某些内容会加快查询速度(索引?)

【问题讨论】:

  • 可能会更快地将单个线程/分叉处理成 2 个简单查询:select from table where title limit 20 然后select from table where description limit 20 有点像,然后使用您的服务器端技术进行连接/列表连接

标签: mysql sql


【解决方案1】:

一个相对简单的解决方案是在这两个字段上合并一个 FULLTEXT 索引,然后使用这个索引进行搜索。

ALTER TABLE table ADD FULLTEXT(title, description);

那么您是否需要执行搜索,您需要执行以下操作:

SELECT id FROM table
WHERE MATCH (title, description) AGAINST ('keyterm');

全文索引搜索是大多数 SQL 数据库中包含的自动解决方案。与做 LIKES 相比,它要快得多。这也针对您的具体情况进行了优化,因为您只对自然语言搜索词感兴趣。

同样,全文索引有一些用于检测相关性的限制算法。你可以阅读更多关于它here

编辑

alter语句中,漏掉了全文索引名,应该是:

ALTER TABLE table ADD FULLTEXT ft_index_name(title, description);

【讨论】:

  • 请注意,这仅适用于 MyISAM 表,不适用于 InnoDB。
  • 非常感谢!!!我对此进行了测试,平均而言,它使我的搜索速度提高了 14 倍!!!!!!!
  • 全文是否也适用于数字?
  • @FrancisAvila 全文搜索自 MySQL 5.6 起在 InnoDB 中得到支持。
【解决方案2】:

试试:

SELECT * FROM table
WHERE MATCH (title,description) AGAINST (searchterm);

确保在标题、描述上一起添加全文索引。

不要试图重新发明轮子。 MATCH 和 AGAINST 是 provided by mysql 来做到这一点,让你的生活更轻松。但是,请注意全文搜索适用于 MyISAM 表。你 can workaround 也是为了 InnoDb。您可以通过更改表来简单地添加 FT 索引:

ALTER TABLE table ADD FULLTEXT(title,description);

【讨论】:

  • 这是唯一可行的答案。提到您需要为这些列添加全文索引,并且必须使用 MyISAM 表。
  • @FrancisAvila 更新了我的答案。
【解决方案3】:

如果您使用带有LIKE '%term%' 的查询,则无法使用索引。仅当您使用 'term%' 之类的查询时才能使用它们。考虑一下带有标签的地址簿,您可以快速找到以字母 L 开头的联系人,但要查找单词中某处带有 on 的联系人,您必须扫描整个地址簿。

更好的选择可能是使用全文索引:

CREATE FULLTEXT INDEX title_desc
ON table (title, description)

然后在查询中:

SELECT title, description FROM table
WHERE MATCH (title, description) AGAINST ('+Pizza')

【讨论】:

    【解决方案4】:

    我会选择 JohnB 或 gtr32x 的答案(全文索引)。为了补充他们的答案,有一种手动方法可以创建简单的全文索引,而且速度非常快......

    将标题和描述拆分为关键字,并将它们放在Keywords 表中,该表具有原始 RSS 文章的外键。确保 Keywords 中的关键字列已编入索引。您可以执行以下操作:

    SELECT DISTINCT ra.* 
    FROM RssArticle ra
    INNER JOIN Keywords k ON k.ArticleID = ra.ArticleID
       WHERE k IN ( 'SearchTerm1', 'SearchTerm2', 'SearchTerm3')
    LIMIT 20;
    

    而且速度很快!

    【讨论】:

      【解决方案5】:

      尝试以下四个查询之一:

      select * from myTable where concat_ws(' ',title,description) like '%pizza%';
      select * from myTable where concat_ws(' ',title,description) regexp '.*pizza+.*';
      select title,description from myTable where concat_ws(' ',title,description) like '%pizza%';
      select title,description from myTable where concat_ws(' ',title,description) regexp '.*pizza+.*';
      

      关键是在搜索之前使用concat

      【讨论】:

      • 这大约快 2 倍,但没有 MATCH AGAINST 快
      【解决方案6】:

      一些提示:在您的选择语句中删除 * 并仅提取搜索条件,并确保为正在搜索的列添加索引。

      SELECT `title`,`description` 
      FROM `table` 
      WHERE `title` LIKE '%$searchterm%' OR `description` LIKE '%$searchterm%' LIMIT 25;
      

      【讨论】:

      • “在你的选择语句中删除 * 并只提取搜索条件” - 你怎么知道他想要检索什么?
      • 我没有,但根据他的 WHERE 子句,我可以确定他至少需要标题和描述。无论如何,指定表而不是通配符总是更好,他问的是如何加快查询速度,第一步是消除通配符。
      • 有一个 LIMIT 20.. 我怀疑它会产生任何可衡量的差异
      • 普通索引在这里对您没有帮助,因为前导 '%'。它们只会占用空间而不会被使用。 (此外,您的搜索词没有正确转义。)您可以使用全文索引和 MATCH 运算符,但只能在 MyISAM 表上使用。
      【解决方案7】:
      1. 您是否为title 和description 创建了索引?
      2. 您应该考虑使用Sphinx 来获得全文搜索功能。

      感谢泰勒的评论。

      我重申我的答案:

      1) 在 title 和 description 列上创建索引,但您的查询将仅限于下面的示例,这对于查找所有相关行并不理想:

      SELECT * 
      FROM 'table' 
      WHERE title LIKE 'searcherm%' OR description LIKE 'searcherm%'
      LIMIT 20;
      

      2) 正如其他人所提到的,使用MySQL Full-Text Search,但您仅限于 MyISAM 表引擎,因为它不适用于 InnoDB。但是,您可以在 MySQL 中混合使用引擎,因此您可以将此表设为 MyISAM,即使您的所有其他表都是 InnoDB。

      3) 使用外部全文搜索引擎,例如Sphinx。这将为您提供更相关的搜索结果(MySQL 全文搜索还有很多不足之处),它的性能会更好,并且可以将全文搜索的负担从您的数据库中抽象出来。

      【讨论】:

      • 索引在这里没有帮助。像 '%foo%' 从不使用索引。这是他真正的问题。
      猜你喜欢
      • 1970-01-01
      • 2012-08-11
      • 2013-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-12
      • 2015-04-02
      相关资源
      最近更新 更多