【问题标题】:What is the efficient way to retrieve(select) data from database?从数据库中检索(选择)数据的有效方法是什么?
【发布时间】:2015-01-28 12:07:58
【问题描述】:

在我的数据库中包含大约 200 万行。这包含每行中的句子集合(不是英语)。

    ![Image of database][1]

例如,如果用户给出 'abcd' ,则与第 1,3 行匹配。因此两者都应该选择。 因为数据检索需要大量时间。我正在使用以下代码来检索数据。如果任何给定的单词与数据库匹配,则应选择这些行。

        sb.append("SELECT Sentence FROM corpus Where ");
         for(int k=0;k<wordList.size();k++){
             sb.append( " Sentence like '%" + wordList.get(k) + "%' OR ");
         } 
         sb.append(" 1=0");
         rs2 = dbc.sqlExecute(sb.toString());

该选择词可能在行中的任何位置。那可能是前面或中间或结尾。我的问题是当用户给出一些词组时,需要花费大量时间来选择匹配的行。有什么适当的方法可以加快我的数据库检索速度吗?我认为索引可能不起作用,因为我不只搜索行的起点。匹配的单词可能包含行中的任何位置。这样做的有效方法是什么?检索需要大量时间。对我来说是个大问题。有人知道正确的方法吗?

【问题讨论】:

  • 查看全文索引,但请注意匹配 > 50% 数据集的 slug 将不会被返回
  • @Strawberry 是否适用于其他语言而不适用于英语?您对此有适当的指导吗?
  • FULLTEXT 支持大多数多字节字符集。例外是对于 Unicode,可以使用 utf8 字符集,但不能使用 ucs2 字符集。请参阅手册。
  • @Strawberry 你有指南或教程与此相关的任何链接吗?" 50% 的数据集不会被返回 "这是什么意思?
  • 去谷歌。键入 MySQL 全文。按回车。单击出现的第一件事。避免提出愚蠢和疏远的问题。

标签: mysql sql database indexing


【解决方案1】:

你不需要 for 循环,只需这样做:

sb.append("SELECT Sentence FROM corpus Where Sentence like '%");

sb.append(wordList);

sb.append("%'");

【讨论】:

  • 搜索效率高吗?我的查询创建速度非常快。问题仍然存在于遍历每一行并选择匹配的行。
【解决方案2】:

我相信有效的解决方案是使用带有绑定参数的PreparedStatement 并在循环中执行它。您可以使用For-Each Loop,并为wordList 中的每个word 绑定参数,然后获取ResultSet(使用try-with-resources)并将返回的sentences 添加到您的List,例如

List<String> sentences = new ArrayList<>();
String sql = "SELECT Sentence FROM corpus WHERE Sentence LIKE ?";
PreparedStatement ps = null;
try {
    ps = conn.prepareStatement(sql);
    for (String word : wordList) {
        ps.setString(1, String.format("%%%s%%", word));
        try (ResultSet rs = ps.executeQuery()) {
            sentences.add(rs.getString(1));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (ps != null) {
        try {
            ps.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

虽然Sentence 列上的 FULLTEXT 索引可能是可取的,但此方法具有使用查询缓存和减小查询大小的好处。 OR 子句只是混淆了情况,因为您想要其中任何一个匹配的行。你也可以考虑Set&lt;String&gt; sentences

【讨论】:

  • 问题是 MySQL 无法在通配符位于字符串之前的通配符搜索中使用索引。该解决方案无法解决这个问题。
  • @Strawberry Edit 添加了关于 FULLTEXT 索引的内容,但如果没有它,您仍然可以获得查询缓存的优势(并且可以减少查询的大小)。
  • @ElliottFrisch 这是否意味着我应该研究 FULLTEXT 索引并添加到​​我的数据库中?
  • @Maduri 看看CREATE INDEX
猜你喜欢
  • 1970-01-01
  • 2014-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-10
  • 2012-08-12
  • 1970-01-01
相关资源
最近更新 更多