【发布时间】:2011-07-13 21:42:57
【问题描述】:
对于我冗长的问题,我提前道歉,如果格式不符合标准(新手),那就去吧。
我有一个表 MY_TABLE 具有以下架构 -
MY_ID |类型 | REC_COUNT 个 1 |一个 | 1 1 |乙| 3 2 |一个 | 0 2 |乙| 0 ……第一列对应一个ID,第二列是一些类型,第三列是一些计数。请注意,MY_ID 列不是主键,可能有许多记录具有相同的 MY_ID。
我想编写一个存储过程,它将接受一个 ID 数组并返回符合以下条件的 ID 子集 - ID 应与表中至少 1 条记录的 MY_ID 字段匹配,并且至少 1 条匹配记录不应具有 TYPE = A OR REC_COUNT = 0。
这是我想出的程序 -
PROCEDURE get_id_subset(
iIds IN ID_ARRAY,
oMatchingIds OUT NOCOPY ID_ARRAY
)
IS
BEGIN
SELECT t.column_value
BULK COLLECT INTO oMatchingIds
FROM TABLE(CAST(iIds AS ID_ARRAY)) t
WHERE EXISTS (
SELECT /*+ NL_SJ */ 1
FROM MY_TABLE m
WHERE (m.my_id = t.column_value)
AND (m.type != 'A' OR m.rec_count != 0)
);
END get_id_subset;
但我真的很关心性能,有些 ID 可以匹配表中的 1000 条记录。 MY_ID 和 TYPE 列上有索引,但 REC_COUNT 列上没有索引。所以我在想如果有超过 1000 行具有匹配的 MY_ID 字段,那么我将只返回 ID 而不应用 TYPE 和 REC_COUNT 谓词。这是这个版本 -
PROCEDURE get_id_subset(
iIds IN ID_ARRAY,
oMatchingIds OUT NOCOPY ID_ARRAY
)
IS
BEGIN
SELECT t.column_value
BULK COLLECT INTO oMatchingIds
FROM TABLE(CAST(iIds AS ID_ARRAY)) t, MY_TABLE m
WHERE (m.my_id = t.column_value)
AND ( ((SELECT COUNT(m.my_id) FROM m WHERE 1) >= 1000)
OR EXISTS (m.type != 'F' OR m.rec_count != 0)
);
END get_id_subset;
但这不能编译,我在内部选择时收到以下错误 -
PL/SQL:ORA-00936:缺少表达式
还有其他写法吗?内部选择需要在连接表上工作。
澄清一下,我同意这个查询的结果集不同。我的假设是,由于 my_id 列上有一个索引,因此执行 count(*) 比将 rec_count 谓词实际应用于 10000 行要便宜得多,因为该列上没有索引。我错了吗?
【问题讨论】:
-
您的第二个 EXISTS 使检查类型和 rec_count 的那个无效,因为第一个 EXISTS 是第二个的子集。
-
发布两个版本查询的执行计划
-
用新版本的查询更新了问题。
标签: sql performance oracle join plsql