我正在使用spring规范与数据库进行交互,但是我可以看到,在生成的sql查询中,存在多余的联接,这使得查询非常慢,这里是代码:
Subquery < Mission > usersAccessSubquery = query.subquery(Mission.class);
Root < Mission > usersAccessSubqueryRoot = usersAccessSubquery.from(Mission.class);
usersAccessSubquery.select(usersAccessSubqueryRoot);
Subquery < Mission > groupesAccessSubquery = query.subquery(Mission.class);
Root < Mission > groupesAccessSubqueryRoot = groupesAccessSubquery.from(Mission.class);
groupesAccessSubquery.select(groupesAccessSubqueryRoot);
Subquery < Mission > groupesAccessSubqueryAdmin = query.subquery(Mission.class);
Root < Mission > groupesAccessSubqueryRootAdmin = groupesAccessSubqueryAdmin.from(Mission.class);
groupesAccessSubqueryAdmin.select(groupesAccessSubqueryRootAdmin);
Predicate usersAccessPredicate = cb.equal(cb.lower(usersAccessSubqueryRoot.join("usersAccess").join("userRef").get("email")), authUserMail.toLowerCase());
Predicate groupesAccessPredicate = cb.equal(cb.lower(groupesAccessSubqueryRoot.join("groupesAccess").join("users").join("userRef").get("email")), authUserMail.toLowerCase());
Predicate groupesAccessPredicateAdmin = cb.equal(cb.lower(groupesAccessSubqueryRootAdmin.join("groupe").get("label")), groupe.getLabel().toLowerCase());
Predicate rootPredicate = cb.conjunction();
usersAccessSubquery.where(usersAccessPredicate);
groupesAccessSubquery.where(groupesAccessPredicate);
groupesAccessSubqueryAdmin.where(groupesAccessPredicateAdmin);
query.where(cb.and(
cb.or(
cb.equal(cb.lower(cb.trim(root.get("createdBy"))), authUserMail.toLowerCase().trim()),
cb.in(root.join("mission").get("id")).value(usersAccessSubquery),
cb.in(root.join("mission").get("id")).value(groupesAccessSubquery),
cb.in(root.join("mission").get("id")).value(groupesAccessSubqueryAdmin)
),
rootPredicate
));
和生成的sql查询:
SELECT DISTINCT user0_.id AS id1_25_,
user0_.created_by AS created_2_25_,
user0_.creation_date AS creation3_25_,
user0_.groupe_id AS groupe_i6_25_,
user0_.role_id AS role_id7_25_,
user0_.update_date AS update_d4_25_,
user0_.updated_by AS updated_5_25_,
user0_.user_ref_id AS user_ref8_25_
FROM users user0_
INNER JOIN user_ref userref1_
ON user0_.user_ref_id = userref1_.id
INNER JOIN user_ref userref2_
ON user0_.user_ref_id = userref2_.id
INNER JOIN user_ref userref3_
ON user0_.user_ref_id = userref3_.id
INNER JOIN groupes groupe4_
ON user0_.groupe_id = groupe4_.id
INNER JOIN mission missions5_
ON groupe4_.id = missions5_.client_entity_id
INNER JOIN groupes groupe6_
ON user0_.groupe_id = groupe6_.id
INNER JOIN mission missions7_
ON groupe6_.id = missions7_.client_entity_id
INNER JOIN groupes groupe8_
ON user0_.groupe_id = groupe8_.id
INNER JOIN mission missions9_
ON groupe8_.id = missions9_.client_entity_id
WHERE ( Lower(userref1_.username) LIKE 'a%'
OR Lower(userref2_.first_name) LIKE 'a%'
OR Lower(userref3_.last_name) LIKE 'a%' )
AND ( missions5_.id IN (SELECT mission10_.id
FROM mission mission10_
INNER JOIN groupes groupe11_
ON mission10_.groupe_id =
groupe11_.id
WHERE Lower(groupe11_.label) =
'tls team')
OR missions7_.id IN (SELECT mission12_.id
FROM mission mission12_
INNER JOIN mission_users_access
usersacces13_
ON mission12_.id =
usersacces13_.mission_id
INNER JOIN users user14_
ON
usersacces13_.users_access_id =
user14_.id
INNER JOIN user_ref userref15_
ON user14_.user_ref_id =
userref15_.id
WHERE Lower(userref15_.departement) =
'test@test.com')
OR missions9_.id IN (SELECT mission16_.id
FROM mission mission16_
INNER JOIN mission_groupes_access
groupesacc17_
ON mission16_.id =
groupesacc17_.mission_id
INNER JOIN groupes groupe18_
ON
groupesacc17_.groupes_access_id =
groupe18_.id
INNER JOIN users users19_
ON groupe18_.id =
users19_.groupe_id
INNER JOIN user_ref userref20_
ON users19_.user_ref_id =
userref20_.id
WHERE Lower(userref20_.departement) =
'test@test.com') )
这是多余的联接:
INNER JOIN user_ref userref1_
ON user0_.user_ref_id = userref1_.id
INNER JOIN user_ref userref2_
ON user0_.user_ref_id = userref2_.id
INNER JOIN user_ref userref3_
ON user0_.user_ref_id = userref3_.id
INNER JOIN groupes groupe4_
ON user0_.groupe_id = groupe4_.id
INNER JOIN mission missions5_
ON groupe4_.id = missions5_.client_entity_id
INNER JOIN groupes groupe6_
ON user0_.groupe_id = groupe6_.id
INNER JOIN mission missions7_
ON groupe6_.id = missions7_.client_entity_id
INNER JOIN groupes groupe8_
ON user0_.groupe_id = groupe8_.id
INNER JOIN mission missions9_
ON groupe8_.id = missions9_.client_entity_id
可以替换为:
INNER JOIN user_ref userref1_
ON user0_.user_ref_id = userref1_.id
INNER JOIN groupes groupe4_
ON user0_.groupe_id = groupe4_.id
INNER JOIN mission missions5_
ON groupe4_.id = missions5_.client_entity_id
这使得执行时间快得多,我认为代码中的请求已得到优化,而且我不知道为什么生成的查询看起来像这样,有人可以解释吗。
答案 0 :(得分:2)
尝试重用路径,例如
Path<?> path = root.join("mission").get("id"));
query.where(cb.and(
cb.or(
cb.equal(cb.lower(cb.trim(root.get("createdBy"))), authUserMail.toLowerCase().trim()),
cb.in(path).value(usersAccessSubquery),
cb.in(path).value(groupesAccessSubquery),
cb.in(path).value(groupesAccessSubqueryAdmin)
),