gpt4 book ai didi

java - hibernate 时最快的 findByName 查询是什么?

转载 作者:搜寻专家 更新时间:2023-10-30 20:06:46 24 4
gpt4 key购买 nike

我确信我可以提高以下 hibernate 的 findByName 查询的性能:

public List<User> findByName(String name) {
session.createCriteria(User.class).add(Restrictions.eq("name", name)).list();
}

瓶颈是 findByName 方法,我不能改用 id。

在我的例子中,我知道名称是唯一的,但向名称属性添加索引注释并没有提高性能。我做了以下事情:

class User {
@Index(name = "nameIdx")
private String name;
}

我应该以哪种方式改进它,甚至更重要的是:我应该首先以哪些方式改进它?我将需要包含此类的所有集合(无论是否为 layz)和 deps 的完整对象。

如果我想要多个 User 对象(并且知道几个名称),我可以改进它吗?

更新1:

@Index 注解并没有提高性能,因为数据库已经有了索引,因为我的唯一约束注解:

@UniqueConstraint(columnNames = {"name"})

更新2:

  1. 仔细阅读答案!

  2. 在 SQL 日志记录的帮助下,我发现真正的问题是尽管我没有提交或刷新事务,但引发了很多更新和插入语句。这背后的原因是我做了(在一个循环中):

    User u = findByName(name);
    if(u == null)
    attach(u = new User(name));

    因此 hibernate 需要在每次 findByName 查询之前将新创建的用户刷新到数据库中。我使用自己的缓存解决方法 (LinkedHashMap) 解决了这个问题。

  3. 我根据 Jens Schauder 的提示进行的另一项改进:

    public Collection<User> findByNames(Collection<String> names) {
    return session.createCriteria(User.class).
    add(Restrictions.in("name", names)).list();
    }
  4. 在将某些用户集合指定为非懒惰时,可以进行进一步的改进:

    @LazyCollection(LazyCollectionOption.FALSE)

    Read this answer以获得更好的选择。

  5. 对我来说最后也是最重要的一个是:用列表替换我的 SortedSet 项目并在 getItems 方法中执行以下操作:

    Set set = new LinkedHashSet(items);
    items.clear();
    items.addAll(set);
    Collections.sort(items, itemComparator);
    return Collections.unmodifiableCollection(items);

    这样,hibernate 就可以处理项目集合(即添加),而无需从数据库加载整个集合。

@Pascal Thivent 和@Jens Schauder:非常感谢!抱歉,我只能接受一个答案:-/

有用的日志记录设置:

log4j.logger.org.hibernate.tool.hbm2ddl=INFO, StdoutApp
log4j.logger.org.hibernate.SQL=INFO, StdoutApp
# additionally provide the information which parameters will be bound:
log4j.logger.org.hibernate.type=TRACE

Another helpful link .

最佳答案

您没有提供足够的信息来获得完整的答案,但这里有一些想法:

  • 你能用这个 id 代替吗? Hibernate 将为按 id 进行选择准备查询,因此这些查询将比其他查询(稍微)快
  • 名称是否正确编入索引?为了这个查询的目的,它应该有一个唯一的键(你在暗示,你期待一个结果)。当然,这样的索引在插入、更新和删除时确实会降低性能。
  • 当我们谈到引用时,这取决于您所说的性能是什么意思:语句返回之前的时间?那么你应该使用延迟加载。它使第一个语句更快,因此可能更快。当然,一旦您的引用文献脱水,您之后会有更多陈述。否则(某些)预加载可能会更快,尽管这在很大程度上取决于细节。
  • 使用缓存,如果可以从缓存中检索,这可能对引用特别有帮助。
  • 调整您的数据库。给它足够的内存,让所有的东西一直保存在内存中。
  • 调整您的网络。对于如图所示的小查询,延迟可能是一个问题
  • 通过将数据库与代码放在同一台机器上来移除网络。假设它足够大。

如您所见,您有大量的调整选项。我唯一期望对这项工作产生良好影响的是考虑索引。当然,当我们获得有关该问题的更多信息(例如完整的表结构、索引、 hibernate 映射、表的大小...)时,这可能会发生变化


根据评论更新:

在调优的时候,第一个问题是:我们需要调优什么?是把Criteria 转换成SQL 语句吗?如果是这样,直接提供一个 sql 语句可能会完成这项工作。

是sql语句的实际执行吗?如果是这样,首先要确定由发布的代码生成的 sql 语句。

我从未见过存储过程使事情变得更快的真实案例。当然,这并不意味着这样的案例不存在。但是现代 rdbms 的优化器非常聪明。

因此,为了正确启动它:设置日志记录,以便您看到每个带有精确时间戳的 sql 语句。以及您正在调整的整个过程的开始和结束时间。如果这是大约数百次执行,您将不得不汇总内容。

这将告诉您是否执行了 sql 语句,哪些语句占用了很多时间,以及它是否是导致问题的 sql 语句。

大多数情况下,sql 语句的性能不佳,但不应仓促下结论。


许多名字部分的更新:

您可以使用 InExpression:http://docs.jboss.org/hibernate/core/3.3/api/org/hibernate/criterion/InExpression.html一次找到多个对象。这将比单个查询更快。

关于java - hibernate 时最快的 findByName 查询是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3048367/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com