Any way to speed up this hierarchical query?
- by RenderIn
I've got a serious performance problem with a hierarchical query that I can't seem to fix.
I am modeling several organization charts in my database, each representing a virtual organization within our company. For example, we have several temporary committees that are created from time to time and there may be a Committee Organizer role at the top of this virtual hierarchy, with several people assigned to the Committee Member role beneath the organizer. Some of our virtual organizations have many levels and several branches at each level.
I have a single table in which I represent all the role assignments. i.e. a ROLE_ID column and a PARENT_ROLE_ID column which is a foreign key to the ROLE_ID column. For each assignment we also store as a column the location in the company where this person has the assignment. For example, the Committee Organizer would have a company-level/ CEO assignment, while the committee members would have department-level assignments such as ACCOUNTING, MARKETING, etc.
So to model the organizer/member relationship for two individuals we would have:
ROLE_ID = 4
PARENT_ROLE_ID = NULL
EMPLOYEE_NUMBER = 213423
COMPANY_LOCATION = CEO
ROLE_ID = 5
PARENT_ROLE_ID = 4
EMPLOYEE_NUMBER = 838221
COMPANY_LOCATION = ACCOUNTING
Here's where things get tricky. I have an application that every person in the organization can log in to. When they log in they should be able to view all the virtual organizations in our company. e.g. the committee members should be able to see the committee organizer and vice-versa. However, only the committee organizer should be able to edit the committee members.
The difficulty is in determining whether an individual (who can have multiple role assignments) has edit access for each other assignment.
While this seems simple in the example, consider a virtual organization in which we have
President at the top, 5 departments directly beneath him, 2 subdepartments below each department. We only want people in the Accounting department to be able to edit individuals in the subdepartments belonging to the Accounting department. They should not have edit access to anybody in the Marketing department or its subdepartments.
To determine edit access when a user views a virtual organization in our company I run a query that executes two inline views: A) Hierarchically query for all assignments in this virtual organization and using SYS_CONNECT_BY_PATH to store the entire path to each user/role/company_location and B) Hierarchically retrieve all the assignments the individual logged in has and using the SYS_CONNECT_BY_PATH to store the entire path to each of these assignments.
The result of the query is all the records from A) plus a boolean determined by joining with B) which flags whether the logged in user has edit access for each record.
Indexes don't seem to be helping... it simply appears that there is too much processing going on to separate all the records and then determine edit access. One issue is that I can't store the SYS_CONNECT_BY_PATH and index it... determining whether an individual record has edit access consists of comparing if: test_record_sys_path LIKE individual_record_sys_path || '%'
Is a materialized view the answer?