【问题标题】:Make performance better checking if a String exists in database提高性能检查数据库中是否存在字符串
【发布时间】:2017-08-31 11:59:25
【问题描述】:
ps = (PreparedStatement) connection.prepareStatement(
      "SELECT nm.id, nid.key, nm.name, nm.languageCode FROM odds.name as nm JOIN (odds.name_id as nid)\r\n"
    + "ON (nm.id = nid.id) where nm.name like '%' and nid.key not like \"vhc%\" and nid.key not like \"vdr%\" and nid.key not like \"vto%\" and nid.key not like \"vbl%\"\r\n"
    + "and nid.key not like \"vf%\" and nid.key not like \"vfl%\" and nid.key not like \"vsm%\" and nid.key not like \"rgs%\"\r\n"
    + "and nid.key not like \"srrgs%\" and nm.typeId=8 and nm.sourceId=-1 and nm.languageCode = 'en'");

    for(Entry <String, Tag> e : allTags.entrySet()) {
        ResultSet rs = ps.executeQuery();
        while(rs.next()) {
            if(rs.getString("name").equals(e.getValue().getTranslation(Language.EN))) {
                e.getValue().setAlternativeKey(rs.getString("name"));
                break;
            }
        }
    }
);

您有什么想法可以让我更快地做到这一点。我将尝试在数据库中查找一个字符串,并为我的对象添加一个额外的信息。但我必须对 1265 个对象执行此操作,因此程序运行大约 80 秒。
提前致谢!

【问题讨论】:

  • 由于 LIKE 语句执行模式匹配,因此成本可能很高。将所有使用 3 个字符后跟百分号的模式的 LIKE 减少到:(substr(nid.key,1,3) not in ("vhc", "vdr", "vto", "vbl", "vfl", "vsm", "rgs")

标签: java sql database performance


【解决方案1】:

首先,在解决性能问题时,为自己准备一个分析工具,它可以告诉你时间花在哪里、给定方法的调用频率等等。

但我认为这个案例足够清楚,可以给出一些更具体的提示。

你一遍又一遍地执行你的 PreparedStatement,对于allTags.entrySet() 中的每个条目一次,总是给你相同的结果,并且在软件内部你过滤掉你感兴趣的行。所以你在做相同的查询 1265 次,对吗?

你在while(rs.next()) 循环中所做的事情让我感到困惑。实际上,您的代码确实如此(在引入一些局部变量、将常量值移出循环之后,...):

    for(Entry <String, Tag> e : allTags.entrySet()) {
        Tag tag = e.getValue();
        String translation = tag.getTranslation(Language.EN);
        ResultSet rs = ps.executeQuery();
        while(rs.next()) {
            if(rs.getString("name").equals(translation)) {
                tag.setAlternativeKey(translation);
                break;
            }
        }
    }

因此,查询结果的唯一作用似乎是决定是否应设置替代键(如果您的Tag 的翻译在ResultSet 中显示为名称) - 该值已由方法调用getTranslation(Language.EN)的结果,独立于任何数据库结果。

我建议您执行一次查询,在HashSet names 中收集name 值,然后如果翻译包含在您的names 集中,则执行allTags 循环设置翻译.这应该会得到与您的代码相同的结果,而且可能要快得多。

【讨论】:

    【解决方案2】:

    打开您选择的 DB 客户端(例如 HeidiSQL)并执行

    explain [the select statement that is originally executed]
    

    这样,MySQL 会向您解释在尝试创建结果时它在做什么以及在哪里浪费时间。

    从那里你可以继续,例如创建索引或更改查询以利用现有索引。

    顺便说一句:

    nm.name like '%' 
    

    看起来很奇怪。这是一个变种

    is not null
    

    后者可能更快。如果其他类似语句中的文本始终相同,则可以通过在插入数据时检查这些条件,添加 int 或 boolean 类型的列并将此检查的结果保存为 integer/boolean 来获得更好的性能。文本本身。检查固定数值比文本搜索快得多。

    【讨论】:

      猜你喜欢
      • 2014-07-06
      • 1970-01-01
      • 1970-01-01
      • 2017-03-18
      • 1970-01-01
      • 2021-12-27
      • 1970-01-01
      • 2017-03-19
      相关资源
      最近更新 更多