如何在 oracle 中优化下面的查询?
how to optimize this below query in oracle?
我的项目中有这些树table,数据量很大:
core_department:最少 300,000 条记录
app_user:最少 3,000 条记录
app_user_部门:最少 3,000 条记录
app_user_excluded_department:最少 50 条记录
core_department
是部门table,每条记录有一个hierarchy
,这个table数据应该是这样来存储分层数据:
id |title |parentId |hierarchy
-----------------------------------
1 |a |null |1
2 |b |1 |1001
3 |c |2 |1001001
4 |d |3 |1001001001
5 |e |3 |1001001002
我将用户授权的部门保存到app_user_department
,未授权的部门保存到app_user_excluded_department
。
例如,如果用户应该有权访问 部门 a 及其所有子级,我将这些记录保存到 app_user_department
:
userId |deparmentId
--------------------
1 |1
并排除 部门 c 及其所有子级,将此记录保存到 app_user_excluded_department
:
userId |deparmentId
--------------------
1 |3
最后,我调用下面的查询来获取特定用户的所有授权部门:
create or replace view user_authorize as
select dp.id, queryResult.userId
from core_department dp
join (
select u.id as userId, dpt.hierarchy as hierarchy
from app_user u
join app_user_department udp
on u.id = udp.userId
join core_department dpt
on udp.departmentId = dpt.id
) queryResult
on dp.hierarchy like queryResult.hierarchy || '%'
minus
select dp.id, queryResult.userId
from core_department dp
join (
select u.id as userId, dpt.hierarchy as hierarchy
from app_user u
join app_user_excluded_department udp
on u.id = udp.userId
join core_department dpt
on udp.departmentId = dpt.id
) queryResult
on dp.hierarchy like queryResult.hierarchy || '%'
select *
from user_authorize ua
where ua.userId = 1
如何优化这个查询?
当您使用 WITH
子句时,Oracle 可能会创建一个临时的 table 并将此类数据存储在其中。这样性能会更好:
create or replace view user_authorize as
WITH queryResult_1 as
( select u.id as userId, dpt.hierarchy as hierarchy
from app_user u
join app_user_department udp
on u.id = udp.userId
join core_department dpt
on udp.departmentId = dpt.id
),
queryResult_2 as
( select u.id as userId, dpt.hierarchy as hierarchy
from app_user u
join app_user_excluded_department udp
on u.id = udp.userId
join core_department dpt
on udp.departmentId = dpt.id
)
select dp.id, queryResult_1.userId
from core_department dp
join queryResult_1
on dp.hierarchy like queryResult_1.hierarchy || '%'
minus
select dp.id, queryResult_2.userId
from core_department dp
join queryResult_2
on dp.hierarchy like queryResult_2.hierarchy || '%'
select *
from user_authorize ua
where ua.userId = 1
我的项目中有这些树table,数据量很大:
core_department:最少 300,000 条记录
app_user:最少 3,000 条记录
app_user_部门:最少 3,000 条记录
app_user_excluded_department:最少 50 条记录
core_department
是部门table,每条记录有一个hierarchy
,这个table数据应该是这样来存储分层数据:
id |title |parentId |hierarchy
-----------------------------------
1 |a |null |1
2 |b |1 |1001
3 |c |2 |1001001
4 |d |3 |1001001001
5 |e |3 |1001001002
我将用户授权的部门保存到app_user_department
,未授权的部门保存到app_user_excluded_department
。
例如,如果用户应该有权访问 部门 a 及其所有子级,我将这些记录保存到 app_user_department
:
userId |deparmentId
--------------------
1 |1
并排除 部门 c 及其所有子级,将此记录保存到 app_user_excluded_department
:
userId |deparmentId
--------------------
1 |3
最后,我调用下面的查询来获取特定用户的所有授权部门:
create or replace view user_authorize as
select dp.id, queryResult.userId
from core_department dp
join (
select u.id as userId, dpt.hierarchy as hierarchy
from app_user u
join app_user_department udp
on u.id = udp.userId
join core_department dpt
on udp.departmentId = dpt.id
) queryResult
on dp.hierarchy like queryResult.hierarchy || '%'
minus
select dp.id, queryResult.userId
from core_department dp
join (
select u.id as userId, dpt.hierarchy as hierarchy
from app_user u
join app_user_excluded_department udp
on u.id = udp.userId
join core_department dpt
on udp.departmentId = dpt.id
) queryResult
on dp.hierarchy like queryResult.hierarchy || '%'
select *
from user_authorize ua
where ua.userId = 1
如何优化这个查询?
当您使用 WITH
子句时,Oracle 可能会创建一个临时的 table 并将此类数据存储在其中。这样性能会更好:
create or replace view user_authorize as
WITH queryResult_1 as
( select u.id as userId, dpt.hierarchy as hierarchy
from app_user u
join app_user_department udp
on u.id = udp.userId
join core_department dpt
on udp.departmentId = dpt.id
),
queryResult_2 as
( select u.id as userId, dpt.hierarchy as hierarchy
from app_user u
join app_user_excluded_department udp
on u.id = udp.userId
join core_department dpt
on udp.departmentId = dpt.id
)
select dp.id, queryResult_1.userId
from core_department dp
join queryResult_1
on dp.hierarchy like queryResult_1.hierarchy || '%'
minus
select dp.id, queryResult_2.userId
from core_department dp
join queryResult_2
on dp.hierarchy like queryResult_2.hierarchy || '%'
select *
from user_authorize ua
where ua.userId = 1