【问题标题】:How to search millions of record in SQL table faster?如何更快地搜索 SQL 表中的数百万条记录?
【发布时间】:2011-08-18 02:59:59
【问题描述】:

我有数百万个域名的 SQL 表。但是现在当我搜索让我们说

SELECT * 
  FROM tblDomainResults 
 WHERE domainName LIKE '%lifeis%'

需要 10 多分钟才能得到结果。我尝试建立索引,但没有帮助。

存储这数百万条记录并在短时间内轻松访问这些信息的最佳方式是什么?

到目前为止,大约有 5000 万条记录和 5 列。

【问题讨论】:

  • 您使用的是什么数据库平台?

标签: sql query-optimization sql-like


【解决方案1】:

全文索引是这里最好的选择 - 如何完成将取决于您使用的 DBMS。

简而言之,确保您在与模式匹配的列上有一个索引有助于提高性能,但是从它的声音来看,您已经尝试过,但没有帮助很多。

【讨论】:

  • 对于这个特定的搜索(LIKE 在字符串的头部使用通配符),列索引根本不会提供任何好处。
【解决方案2】:

很可能,您尝试了一个传统索引,它不能用于优化 LIKE 查询,除非该模式以固定字符串开头(例如 'lifeis%')。

您的查询需要的是全文索引。现在大多数 DBMS 都支持它。

【讨论】:

    【解决方案3】:

    您可能要考虑的一件事是为此类查找使用单独的搜索引擎。例如,您可以使用 SOLR (lucene) 服务器搜索并检索与您的搜索匹配的条目的 id,然后按 id 从数据库中检索数据。即使不得不打两个不同的电话,它很可能最终会更快。

    【讨论】:

      【解决方案4】:

      停止使用 LIKE 语句。您可以使用 fulltext search,但它需要 MyISAM 表,并不是那么好的解决方案。

      我建议您检查可用的第 3 方解决方案 - 例如 LuceneSphinx
      它们会更出色。

      【讨论】:

        【解决方案5】:

        只要索引本身不包含查找(“书签查找”)数据,索引就会变慢。例如,如果您的索引有 2 列、ID 和 NAME,但您选择 *(总共 5 列),数据库必须读取前两列的索引,然后查找其他 3 列其他地方效率较低的数据结构。

        在这种情况下,由于“喜欢”,您的索引无法使用。这类似于不在查询中放置任何 where 过滤器,它将完全跳过索引,因为它必须读取整个表,无论如何它都会这样做(“表扫描”)。有一个阈值(我认为大约 35-50%,引擎通常会翻转到这个位置)。

        简而言之,您似乎不太可能需要数据库中的所有 5000 万行用于生产应用程序,但如果您需要...使用内存更大的机器并尝试将这些数据保存在内存中的方法。也许 No-SQL DB 会是更好的选择——mongoDB、couch DB、tokyo cabinet。诸如此类的事情。祝你好运!

        【讨论】:

          【解决方案6】:

          您可以尝试将域分成块,然后自行搜索这些块。几年前,当我需要在句子中搜索单词时,我做过类似的事情。我没有可用的全文搜索,所以我将句子分解成一个单词列表并搜索这些单词。词条被编入索引后,很快就找到结果了。

          【讨论】:

            【解决方案7】:

            假设您的 5000 万行表包含重复项(也许这是问题的一部分),并假设 SQL Server(语法可能会改变,但大多数 RDBMS 的概念相似),另一种选择是将域存储在查找中表,例如

            CREATE TABLE dbo.Domains
            (
                DomainID INT IDENTITY(1,1) PRIMARY KEY,
                DomainName VARCHAR(255) NOT NULL
            );
            CREATE UNIQUE INDEX dn ON dbo.Domains(DomainName);
            

            当您加载新数据时,检查是否有任何域名是新的 - 并将它们插入到域表中。然后在您的大表中,您只需包含 DomainID。这不仅会使您的 5000 万行表变得更小,而且还会使这样的查找更有效率。

            SELECT * -- please specify column names
            FROM dbo.tblDomainResults AS dr
            INNER JOIN dbo.Domains AS d
            ON dr.DomainID = d.DomainID
            WHERE d.DomainName LIKE '%lifeis%';
            

            当然,除了最小的表之外,避免使用前导通配符的 LIKE 子句总是有帮助的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-03-15
              • 2013-11-10
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多