Oracle SQL 查询与 CASE WHEN EXISTS 子查询优化
Oracle SQL query with CASE WHEN EXISTS subquery optimization
我正在使用以下查询在 Oracle 11g (11.2.0.3.0).
中创建视图
CREATE OR REPLACE FORCE VIEW V_DOCUMENTS_LIST
(
ID_DOC,
ATTACHMENTS_COUNT,
TOTAL_DIMENSION,
INSERT_DATE,
ID_STATE,
STATE,
ID_INSTITUTE,
INSTITUTE,
HASJOB
)
AS
SELECT D.ID_DOC,
COUNT (F.ID_FILE) AS ATTACHMENTS_COUNT,
CASE
WHEN SUM (F.DIMENSION) IS NULL THEN 0
ELSE SUM (F.DIMENSION)
END
AS TOTAL_DIMENSION,
D.INSERT_DATE,
D.ID_STATE,
S.STATE_DESC AS STATE,
D.ID_INSTITUTE,
E.NAME AS INSTITUTE,
CASE
WHEN EXISTS (SELECT D.ID_DOC FROM JOB) THEN 'true'
ELSE 'false'
END
AS HASJOB
FROM DOCUMENTS D
LEFT JOIN FILES F ON D.ID_DOC = F.ID_DOC
JOIN STATES S ON D.ID_STATE = S.ID_STATE
JOIN INSTITUTES E ON D.ID_INSTITUTE = E.ID_INSTITUTE
GROUP BY D.ID_DOC,
D.INSERT_DATE,
D.ID_STATE,
S.STATE_DESC,
D.ID_INSTITUTE,
E.NAME;
然后我查询该视图以获取 ASPX
页面中 DataGridView
的值。
SELECT *
FROM V_DOCUMENTS_LIST
ORDER BY ID_STATE DESC, INSTITUTE, INSERT_DATE DESC;
相关表和关系
文档;文件;乔布斯;
文件 (1-1) <----> (0-N) 文件
作业 (0-1) <----> (0-N) 文档
查询视图,我得到了完整的文档列表及其所有相关信息(ID、描述、日期、状态等)以及每个文档的信息:
- 附件总数;
- 附件总尺寸;
- 布尔值,指示是否至少有一个
JOB
关联到 DOCUMENT
或不.
一切正常,直到视图包含几千条记录。现在记录数量在增加,视图上的 SELECT * FROM
大约需要 2:30 分钟,包含 15.000-20.000 条记录。
我知道我的视图中真正耗时的部分是嵌套的 SELECT
:
CASE
WHEN EXISTS (SELECT D.ID_DOC FROM JOB) THEN 'true'
ELSE 'false'
END
AS HASJOB
如何优化我的视图?
要解决不存在的问题,您可以添加一个连接:
LEFT JOIN (select distinct id_doc from JOB) J
ON d.id_doc = J.id_doc
Has_job 列为:
CASE
WHEN j.id_doc is not null THEN 'true'
ELSE 'false'
END AS HASJOB
PS:您当前的实现有问题,因为如果作业 table 有行,SELECT D.ID_DOC FROM JOB
将始终包含行。它等同于 select * from job
,因为 exists 只是测试行的存在。逻辑上正确的实现是:SELECT 1 FROM JOB j where j.id_doc = D.ID_DOC
.
您要在 table JOB
上建立完整索引,将 WHERE
子句放入查询中:
SELECT D.ID_DOC FROM JOB
我正在使用以下查询在 Oracle 11g (11.2.0.3.0).
中创建视图CREATE OR REPLACE FORCE VIEW V_DOCUMENTS_LIST
(
ID_DOC,
ATTACHMENTS_COUNT,
TOTAL_DIMENSION,
INSERT_DATE,
ID_STATE,
STATE,
ID_INSTITUTE,
INSTITUTE,
HASJOB
)
AS
SELECT D.ID_DOC,
COUNT (F.ID_FILE) AS ATTACHMENTS_COUNT,
CASE
WHEN SUM (F.DIMENSION) IS NULL THEN 0
ELSE SUM (F.DIMENSION)
END
AS TOTAL_DIMENSION,
D.INSERT_DATE,
D.ID_STATE,
S.STATE_DESC AS STATE,
D.ID_INSTITUTE,
E.NAME AS INSTITUTE,
CASE
WHEN EXISTS (SELECT D.ID_DOC FROM JOB) THEN 'true'
ELSE 'false'
END
AS HASJOB
FROM DOCUMENTS D
LEFT JOIN FILES F ON D.ID_DOC = F.ID_DOC
JOIN STATES S ON D.ID_STATE = S.ID_STATE
JOIN INSTITUTES E ON D.ID_INSTITUTE = E.ID_INSTITUTE
GROUP BY D.ID_DOC,
D.INSERT_DATE,
D.ID_STATE,
S.STATE_DESC,
D.ID_INSTITUTE,
E.NAME;
然后我查询该视图以获取 ASPX
页面中 DataGridView
的值。
SELECT *
FROM V_DOCUMENTS_LIST
ORDER BY ID_STATE DESC, INSTITUTE, INSERT_DATE DESC;
相关表和关系
文档;文件;乔布斯;
文件 (1-1) <----> (0-N) 文件
作业 (0-1) <----> (0-N) 文档
查询视图,我得到了完整的文档列表及其所有相关信息(ID、描述、日期、状态等)以及每个文档的信息:
- 附件总数;
- 附件总尺寸;
- 布尔值,指示是否至少有一个
JOB
关联到DOCUMENT
或不.
一切正常,直到视图包含几千条记录。现在记录数量在增加,视图上的 SELECT * FROM
大约需要 2:30 分钟,包含 15.000-20.000 条记录。
我知道我的视图中真正耗时的部分是嵌套的 SELECT
:
CASE
WHEN EXISTS (SELECT D.ID_DOC FROM JOB) THEN 'true'
ELSE 'false'
END
AS HASJOB
如何优化我的视图?
要解决不存在的问题,您可以添加一个连接:
LEFT JOIN (select distinct id_doc from JOB) J
ON d.id_doc = J.id_doc
Has_job 列为:
CASE
WHEN j.id_doc is not null THEN 'true'
ELSE 'false'
END AS HASJOB
PS:您当前的实现有问题,因为如果作业 table 有行,SELECT D.ID_DOC FROM JOB
将始终包含行。它等同于 select * from job
,因为 exists 只是测试行的存在。逻辑上正确的实现是:SELECT 1 FROM JOB j where j.id_doc = D.ID_DOC
.
您要在 table JOB
上建立完整索引,将 WHERE
子句放入查询中:
SELECT D.ID_DOC FROM JOB