大家好,在项目中碰到如下问题:
hibernate 映射表的时候使用联合主键
例子如下:
商品表:Item,主键为联合主键ItemId
代码如下 public class ItemId{
@column
Long itemId;
@column
Long userId;
}
@Table(...)
public class Item{
@Id
ItemId id;
@column
Date createDate;
@column
boolean deleted;
...
}
三个手动创建索引如下: itemId 主键索引
userId 主键索引
itemId, userId 联合索引 数据库表为InnerDB 更新一条语句示例如下: public void softDeleteItem(long itemId, long userId){
session.createQuery("update Item set deleted = :deleted WHERE id=:id")
.setParameter("deleted", 1)
.setParameter("id", new ItemId(itemId, userId))
.executeQuery();
}
通过上面的更新语句hibernate产生如下SQL语句
update item set delete=? where (itemId, userid) = (?, ?) 在后台查询这条sql语句非常耗时,在item表数据量达到百万级级的时候好使就需要2~3秒
通过查询返回的详细参数可以看到Mysql做全表查询了,而且锁表了,并没有使用索引。
之后为了解决线上问题,就做出更改如下 public void softDeleteItem(long itemId, long userId){
session.createQuery("update Item set deleted = :deleted WHERE id.itemId=:itemId AND id.userId = :userId")
.setParameter("deleted", 1)
.setParameter("itemId", itemId)
.setParameter("userId", userId)
.executeQuery();
} hibernate生成的语句如下:
update item set delete=? where itemId = ? and userid=? 效率立即上去了,使用了索引,更新只需要毫秒级的时间。 故,两个问题: 1. hibernate为什么会生成
update item set delete=? where (itemId, userid) = (?, ?)
而不是
update item set delete=? where itemId = ? and userid = ? 2. 上面两条sql语句在mysql执行的效率为什么不一样 ? 何解?
备注:
Mysql官方文档对行子查询的说明如下:
hibernate 映射表的时候使用联合主键
例子如下:
商品表:Item,主键为联合主键ItemId
代码如下 public class ItemId{
@column
Long itemId;
@column
Long userId;
}
@Table(...)
public class Item{
@Id
ItemId id;
@column
Date createDate;
@column
boolean deleted;
...
}
三个手动创建索引如下: itemId 主键索引
userId 主键索引
itemId, userId 联合索引 数据库表为InnerDB 更新一条语句示例如下: public void softDeleteItem(long itemId, long userId){
session.createQuery("update Item set deleted = :deleted WHERE id=:id")
.setParameter("deleted", 1)
.setParameter("id", new ItemId(itemId, userId))
.executeQuery();
}
通过上面的更新语句hibernate产生如下SQL语句
update item set delete=? where (itemId, userid) = (?, ?) 在后台查询这条sql语句非常耗时,在item表数据量达到百万级级的时候好使就需要2~3秒
通过查询返回的详细参数可以看到Mysql做全表查询了,而且锁表了,并没有使用索引。
之后为了解决线上问题,就做出更改如下 public void softDeleteItem(long itemId, long userId){
session.createQuery("update Item set deleted = :deleted WHERE id.itemId=:itemId AND id.userId = :userId")
.setParameter("deleted", 1)
.setParameter("itemId", itemId)
.setParameter("userId", userId)
.executeQuery();
} hibernate生成的语句如下:
update item set delete=? where itemId = ? and userid=? 效率立即上去了,使用了索引,更新只需要毫秒级的时间。 故,两个问题: 1. hibernate为什么会生成
update item set delete=? where (itemId, userid) = (?, ?)
而不是
update item set delete=? where itemId = ? and userid = ? 2. 上面两条sql语句在mysql执行的效率为什么不一样 ? 何解?
备注:
Mysql官方文档对行子查询的说明如下:
有这样的语法。
oracle 和 sqlserver好像也有。
看别人写过,自己没有故意这么写过SQL。