Java hibernate最快的findByName查询是什么?

Java hibernate最快的findByName查询是什么?,java,database,performance,hibernate,Java,Database,Performance,Hibernate,我相信我可以提高hibernate的以下findByName查询的性能: public List<User> findByName(String name) { session.createCriteria(User.class).add(Restrictions.eq("name", name)).list(); } 我应该以哪种方式改进它,或者更重要的是:我应该首先以哪种方式改进它?我将需要这个类的所有集合(layz或不是)和dep的完整对象 或者,如果我想要几个用户对象(

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

public List<User> findByName(String name) {
  session.createCriteria(User.class).add(Restrictions.eq("name", name)).list();
}
我应该以哪种方式改进它,或者更重要的是:我应该首先以哪种方式改进它?我将需要这个类的所有集合(layz或不是)和dep的完整对象

或者,如果我想要几个用户对象(并且知道几个名称),我可以改进它吗

更新1:

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

@UniqueConstraint(columnNames = {"name"})
更新2:

  • 仔细阅读答案

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

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

  • 我通过Jens Schauder的提示做了另一个改进:

    public Collection<User> findByNames(Collection<String> names) {
       return session.createCriteria(User.class).
              add(Restrictions.in("name", names)).list();
    }
    
    为了得到更好的选择

  • 最后也是最重要的一点是:用列表替换SortedSet项,并在getItems方法中执行以下操作:

    Set set = new LinkedHashSet(items);
    items.clear();
    items.addAll(set);
    Collections.sort(items, itemComparator);
    return Collections.unmodifiableCollection(items);
    
    这样,hibernate就可以处理items集合(即添加),而无需从数据库加载整个集合

  • @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
    

    .

    您没有提供足够的信息来完整回答问题,但以下是一些想法:

    • 你能用身份证吗?Hibernate将为select by id准备查询,因此这些查询将(稍微)比其他查询快
    • 名称的索引是否正确?对于这个查询,它应该有一个唯一的键(你暗示的是,你期望的是一个结果)。当然,这样的索引在插入、更新和删除时会降低性能
    • 当我们谈到引用时,它取决于您所说的性能:语句返回之前的时间?那么您应该使用延迟加载。它使第一个语句更快,因此可能更快。当然,一旦你的参考文献脱水,你会有更多的陈述。否则(一些)急切的加载可能会更快,尽管这在很大程度上取决于细节
    • 使用缓存,如果可以从缓存中检索引用,这可能特别有助于引用
    • 调整数据库。给它足够的内存,让它能一直记住所有的东西
    • 调整你的网络。对于如图所示的小查询,延迟可能是一个问题
    • 通过将数据库与代码放在同一台计算机上来删除网络。假设它足够大
    正如您所看到的,您有大量的调优选项。我唯一希望这项工作取得良好效果的方法就是考虑一个指数。当然,当我们获得有关问题的更多信息(例如,完整的表结构、索引、hibernate映射、表的大小等)时,这种情况可能会改变


    根据评论更新:

    调整时,第一个问题是:我们需要调整什么? 是将标准转换为SQL语句吗?如果是这样的话,直接提供sql语句就可以完成这项工作

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

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

    因此,为了正确地开始这项工作:设置日志记录,以便查看每个带有精确时间戳的sql语句。以及您正在调整的整个过程的开始和结束时间。如果这是关于数百次处决,你就得把事情搞糟

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

    大多数情况下,sql语句的性能很差,但我们不应该急于下结论


    关于多个名称部分的更新:

    您可以使用非表达式:一次查找多个对象。这将比单个查询更快

    在我的例子中,我知道名称是唯一的,但是向name属性添加索引注释并没有提高性能。瓶颈是
    findByName
    方法

    我不会相信这个。。。直到你拿出一些数字证明我错了:)所以:

    • 仔细检查索引是否已生成(检查DDL语句和数据库)。此查询需要此列上的索引
    • 检查生成的查询的查询计划(应该类似于
      SELECT*FROM USER u,其中u.NAME='foo'
      )和执行时间

    以后,您可以考虑激活第二级缓存并缓存查询。但数据库才是起点(过早缓存东西只会隐藏真正的问题)


    测量东西!如果你不能测量它,你就不能改进它--开尔文勋爵。

    很抱歉没有提供足够的信息。这是一个商业项目,我会尽量向您提供最大限度的信息,而不会让我的老板生气。第一:我不能改用id。我认为我可以使用本机sql查询或存储过程?这会提高性能吗?当表很小时,索引可能不会被使用,尽管它看起来像是一个完美的匹配。当然,完全有可能OP添加了注释,但没有更改模式:)@Jens Schauder:我应该如何更改模式?(我在运行drop+create架构之前
    @LazyCollection(LazyCollectionOption.FALSE)
    
    Set set = new LinkedHashSet(items);
    items.clear();
    items.addAll(set);
    Collections.sort(items, itemComparator);
    return Collections.unmodifiableCollection(items);
    
    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