林在电话/的ServiceDesk软件的工作与这种布局(火鸟2.1):嵌套优化查询的WHERE子句
呼叫是通过选择一个区域,从该区域呼叫类型的打开(表呼叫,区域和类型)
用户分配轮廓它说哪些领域和类型,他们可以查看或编辑电话(表用户和表谱)
根据不同的配置文件,用户可能能够查看或编辑ALL类型一定面积的(表profile_areas),或 只是查看或编辑电话的选择类型(表profile_types)
用户可能有特殊的许可,除了能查看分配在个人资料方面, 也是能够查看他们打开任何呼叫(上表的配置文件布尔列)
林发布主体结构的精简,列重命名版本。我不认为我能在 上发布真正的表格,这些表格涵盖了300多个领域以及更多的FK表格。
这是关于通话和用户权限的最基本的结构。
CREATE TABLE CALLS (
CALLID INTEGER, /* PK */
AREAID INTEGER, /* FK ON TABLE AREAS */
TYPEID INTEGER, /* FK ON TABLE TYPES */
USERID_OPENED_BY, /* FK ON TABLE USERS */
STATUS CHAR(1)
);
CREATE TABLE AREAS (
AREAID INTEGER, /* PK */
AREA_NAME VARCHAR(50),
);
CREATE TABLE TYPES (
TYPEID INTEGER, /* PK */
AREAID INTEGER, /* FK ON TABLE AREAS */
TYPE_NAME VARCHAR(50),
);
CREATE TABLE USERS (
USERID INTEGER, /* PK */
PROFILEID INTEGER, /* FK ON TABLE PROFILES */
USER_NAME VARCHAR(50),
);
CREATE TABLE PROFILES (
PROFILEID INTEGER, /* PK */
PROFILE_NAME VARCHAR(50),
VIEW_ALL_CALLS_OPENED CHAR(1) /* if true, user can always view any calls he opened, regardless of area or type */
);
CREATE TABLE PROFILES_AREAS (
PAREA_ID INTEGER, /* PK */
PROFILEID INTEGER, /* FK ON TABLE PROFILES */
AREAID INTEGER (FK),
CAN_VIEW_AREA CHAR(1), /* can view any calls on this area, regardless of types */
CAN_EDIT_AREA CHAR(1) /* can edit any calls on this area, regardless of types */
);
CREATE TABLE PROFILES_TYPES (
PTYPE_ID INTEGER, /* PK */
PROFILEID INTEGER, /* FK ON TABLE PROFILES */
TYPEID INTEGER, /* FK ON TABLE TYPES */
CAN_VIEW_TYPE CHAR(1), /* can view any calls of this type */
CAN_EDIT_TYPE CHAR(1) /* can edit any calls of this type */
);
我们开始看到我们的第一个客户达到10+万次呼叫标记,以及任何主要的简单查询也开始变得很慢。
在对查询计划进行分析时,似乎所有索引都已正确编制索引,但即使查询 总共返回了5个左右的结果,索引读取的数量几乎总是显示1000万左右。
这个问题似乎是因为配置文件可能有很多不同的变体,我们并没有成功地使用连接来构建where子句,这反过来又创建了大量不同的OR子句,我们必须处理。
最糟糕的情况是,因为这样的:
1.用户可以查看他开
2.用户可以浏览一些地区的所有呼叫,但不是所有的
3.用户可以查看某些类型的,但不是所有的
这是留给我们这样的事(让说的用户ID为“1”):
SELECT CALLID FROM CALLS
WHERE
CALLS.USERID_OPENED_BY = 1 /* .User can view all calls he opened */
OR (
CALLS.AREAID IN (1,2,3) /* areas the user can view, in his profile. we tried using a subselect here and things just went from bad to much, much worse */
OR
CALLS.TYPEID IN (1,2,3) /* types the user can view, in his profile. we tried using a subselect here and things just went from bad to much, much worse */
)
那种where子句正在杀死性能。
有人建议我们尝试将OR分解为不同的查询并加入联合,但其他一些因素使其非常麻烦。
理想情况下,我们试图限制我们的客户使用如此大范围的配置文件权限变化,但相反,这种趋势似乎是更新,更晦涩的配置类型的需求(这就是为什么“查看所有打开的电话” “例如被执行)。
我们应该关注哪些更好的策略?
我们在这里讨论了多少个电话? – bluevector
不好意思问这样一个愚蠢的问题,但显然你把索引放在FK领域不是吗? – Sebas
为什么用户需要查看他们打开的所有呼叫以及他们分配的区域/类型中的所有呼叫?他们发起的所有呼叫是否都包含在他们分配的区域和/或类型中? 他们不能在他们无权查看的区域/类型中发起呼叫。他们似乎会(可能只应该)要么查看他们所分配的区域/类型中的所有呼叫或所有呼叫。 – Sean