我可以设置任何Hibernate属性来查看所有慢速查询吗?我对那些花费太多时间返回结果集的查询感兴趣。我正在使用Spring和Hibernate,通过...
问题描述
我可以设置任何Hibernate属性来查看所有慢速查询吗?我对那些花费太多时间返回结果集的查询感兴趣。
我将Spring与Hibernate结合使用,通过applicationContext.xml
Spring配置文件进行配置。
解决方法:
我有2条建议:
我过去使用IronGrid的P6Spy和IronTrack SQL,这是一个不错的组合(请参阅this blog post)。但请注意:
功能
易于配置,在大多数情况下,您只需更改驱动程序类名net.sf.log4jdbc.DriverSpy和前置“ jdbc:log4”到您现有的jdbc网址,设置您的日志记录类别并您准备好了!
在记录的输出中,对于准备好的语句,绑定参数为自动插入SQL输出。这大大改善了许多人的可读性和调试案例。
SQL时序信息可以生成,以帮助识别需要多长时间SQL语句可以运行,有助于识别正在运行的语句太慢了,可以发布这些数据用附带的工具处理产生分析报告数据快速识别您的慢速SQL应用]]。SQL连接号信息将生成以帮助识别连接池或线程问题。
与任何具有JDK 1.4及更高版本的基础JDBC驱动程序一起使用,以及SLF4J 1.x。
开源软件,根据商业友好型Apache 2.0获得许可执照:http://www.apache.org/licenses/LICENSE-2.0
这是一个非常常见的问题,所以我决定将此答案转换为full-blown article。
休眠5.4
此慢查询日志功能自Hibernate ORM 5.4.5开始提供,并在给定JPQL,Criteria API或本机SQL查询的执行时间超过您先前配置的某个阈值时通知您。
配置
为了激活休眠慢速查询日志,您需要将hibernate.session.events.log.LOG_QUERIES_SLOWER_THAN_MS
属性设置为大于0
的值,代表查询执行阈值。
在我们的情况下,任何花费超过25
毫秒的查询都会触发Hibernate慢速查询日志。
Spring Boot配置
如果使用Spring Boot,则可以在application.properties
配置文件中设置此Hibernate设置:
hibernate.session.events.log.LOG_QUERIES_SLOWER_THAN_MS=25
Java EE配置
如果使用的是Java EE,则可以在persistence.xml
配置文件中进行设置:
记录器配置
您还需要将org.hibernate.SQL_SLOW
记录器设置为至少INFO
级别。
如果使用的是Logback,则可以如下设置:
就是这样!
测试时间
假设我们在应用程序中定义了以下Post
实体类:
Post
实体的映射如下:
@Entity(name = "Post")
@Table(name = "post")
public class Post {
@Id
private Long id;
private String title;
@Column(name = "created_on")
@CreationTimestamp
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
//Getters and setters omitted for brevity
}
我们将保留5000个Post
实体,以便我们有足够的数据来生成耗时超过25毫秒的查询:
LongStream
.rangeClosed(1, 5000)
.forEach(i -> {
entityManager.persist(
new Post()
.setId(i)
.setTitle(
String.format(
"High-Performance Java Persistence book - page %d review",
i
)
)
.setCreatedBy("Vlad Mihalcea")
);
if(i % 50 == 0 && i > 0) {
entityManager.flush();
}
});
检测慢的JPQL查询
执行以下JPQL查询时:
List posts = entityManager
.createQuery(
"select p " +
"from Post p " +
"where lower(title) like :titlePattern " +
"order by p.createdOn desc", Post.class)
.setParameter(
"titlePattern",
"%Java%book%review%".toLowerCase()
)
.setFirstResult(1000)
.setMaxResults(100)
.getResultList();
Hibernate生成以下慢查询日志条目:
o.h.SQL_SLOW -
SlowQuery: 32 milliseconds.
SQL:
'PgPreparedStatement [
select
p.id as id1_0_,
p.created_by as created_2_0_,
p.created_on as created_3_0_,
p.title as title4_0_
from
post p
where lower(p.title) like '%java%book%review%'
order by p.created_on desc
limit 100
offset 1000
]'
检测缓慢的Criteria API查询
[执行此Criteria API查询时:
CriteriaBuilder builder = entityManager
.getCriteriaBuilder();
CriteriaQuery postQuery = builder
.createQuery(Post.class);
Root post = postQuery.from(Post.class);
postQuery
.where(
builder.like(
builder.lower(post.get("title")),
"%Java%book%review%".toLowerCase()
)
)
.orderBy(
builder.desc(post.get("createdOn"))
);
List posts = entityManager.createQuery(
postQuery
)
.setFirstResult(1000)
.setMaxResults(100)
.getResultList();
Hibernate生成缓慢的查询日志条目,就像这样:
o.h.SQL_SLOW -
SlowQuery: 27 milliseconds.
SQL: 'PgPreparedStatement [
select
p.id as id1_0_,
p.created_by as created_2_0_,
p.created_on as created_3_0_,
p.title as title4_0_
from
post p
where
lower(p.title) like '%java%book%review%'
order by p.created_on desc
limit 100
offset 1000
]'
检测慢速本机SQL查询List posts = entityManager
.createNativeQuery(
"SELECT p.* " +
"FROM post p " +
"WHERE LOWER(p.title) LIKE :titlePattern " +
"ORDER BY p.created_on DESC", Post.class)
.setParameter(
"titlePattern",
"%Java%book%review%".toLowerCase()
)
.setFirstResult(1000)
.setMaxResults(100)
.getResultList();
我们收到由Hibernate编写的慢速查询日志消息:
o.h.SQL_SLOW -
SlowQuery: 27 milliseconds.
SQL: 'PgPreparedStatement [
SELECT
p.*
FROM post
p
WHERE
LOWER(p.title) LIKE '%java%book%review%'
ORDER BY p.created_on DESC
LIMIT 100
OFFSET 1000
]'
在我们的案例中,应用程序查询类型不会影响慢查询日志,因为JPQL和Criteria API均会生成与我们在上一个测试案例中使用的本机SQL相似的SQL查询。