使用内连接与子查询的DB2+Hibernate查询,哪个性能更优?
我有两个返回相同结果的查询,想了解哪个性能更高效。使用DB2和Hibernate,且所有主键和外键都已建立索引。
数据模型
Order { orderId } OrderItem { orderItemId orderId productId } Product { productId }
Order与OrderItem是一对多关系,多个OrderItem关联一个Product。需求是检索与指定产品(参数:productId)关联的订单。
两个查询语句
1. 内连接查询
Select distinct o from Order o inner join OrderItem oi on o.id = oi.orderId and oi.productId = :productId
2. 带COUNT子查询的WHERE语句查询
Select o from Order o where (Select count(oi) from OrderItem oi where oi.orderId = o.id and oi.productId = :productId ) > 0
性能对比分析
内连接+DISTINCT 查询:
DB2会先通过OrderItem.productId的索引快速定位到匹配指定产品的OrderItem记录,再关联Order表获取订单数据。由于一个订单可能对应多条OrderItem,所以需要DISTINCT去重。如果OrderItem上有(productId, orderId)的复合索引,这个过程会非常高效;即使只有单字段索引,优化器也能快速完成关联。DISTINCT的去重开销在数据量不是极大的情况下,通常不会成为性能瓶颈。COUNT子查询 查询:
这是一个相关子查询,会对Order表中的每一行执行一次子查询,判断是否存在关联的目标OrderItem。虽然理论上DB2可能会把COUNT>0优化为“找到第一条匹配就停止”,但实际执行中,这种逐行遍历的方式在Order表数据量大时,性能会远不如内连接——尤其是当匹配的订单数量远小于总订单数时,内连接可以直接过滤出目标订单,而子查询要遍历大量无关的订单记录,效率极低。
最优写法建议
如果想进一步优化性能,可以改用EXISTS替代内连接+DISTINCT,避免去重开销:
Select o from Order o where exists ( select 1 from OrderItem oi where oi.orderId = o.id and oi.productId = :productId )
EXISTS只判断关联记录是否存在,找到第一条匹配就停止查询,不需要处理重复数据,性能通常比前两种写法都更优。
内容的提问来源于stack exchange,提问作者kaizokun

