这个问题的主要目标是优化和更快的运行时间。
在Stored Proc中进行大量处理后,我最终返回如下计数:
OPEN cv_1 FOR
SELECT COUNT(*) num_of_members
FROM HOUSEHOLD_MEMBER a,
HOUSEHOLD b
WHERE RTRIM(LTRIM(a.mbr_last_name)) LIKE v_MBR_LAST_NAME || '%'
AND a.number = '01'
AND a.code = v_CODE
AND a.ssn_head = v_SSN_HEAD
AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB;
但在我调用SP的代码中,不需要实际计数。它只关心计数大于1.
问题:
答案 0 :(得分:2)
如果您不需要实际数据,并且只想知道是否至少有1,您可以使用ROWNUM对其进行优化:
OPEN cv_1 FOR
SELECT 1 has_at_least_one_member
FROM HOUSEHOLD_MEMBER a,
HOUSEHOLD b
WHERE RTRIM(LTRIM(a.mbr_last_name)) LIKE v_MBR_LAST_NAME || '%'
AND a.number = '01'
AND a.code = v_CODE
AND a.ssn_head = v_SSN_HEAD
AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB
AND ROWNUM = 1;
Oracle会优化此功能,以便在找到匹配项后立即停止处理。
在一个不相关的说明中,我建议(根据duffymo的说明)删除围绕a.mbr_dob的TO_CHAR并在v_DOB周围添加TO_DATE。这样,如果a.mbr_dob上恰好有索引,Oracle就有机会使用它。
答案 1 :(得分:1)
我不会想到在count(*)上引入过滤器会对性能有所帮助,但正如已经说过的那样,你可以用HAVING子句来做这件事。
你最大的瓶颈可能在于你的加入。
WHERE RTRIM(LTRIM(a.mbr_last_name)) LIKE v_MBR_LAST_NAME || '%'
这条线路无济于事。无论何时开始执行字段功能,都无法使用正确的索引,因此如果您可以避免修剪名称,这可能有所帮助。
AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB;
这看起来像是最大的问题。如果v_DOB可以转换为查询之前的日期,那将有所帮助。或者,我认为将语句切换为使用TO_DATE可能有所帮助。
优化这一点的最佳方法是获得解释计划:
EXPLAIN PLAN FOR
...
答案 2 :(得分:1)
我的经验是,从游标中获取单行通常比检索COUNT()更快。如果您需要知道匹配数据存在但不关心行数,这将非常有用。在这种情况下,代码可以重写为
DECLARE
bRow_found BOOLEAN := FALSE;
BEGIN
FOR aRow IN (SELECT a.mbr_last_name
FROM HOUSEHOLD_MEMBER a,
HOUSEHOLD b
WHERE RTRIM(LTRIM(a.mbr_last_name)) LIKE v_MBR_LAST_NAME || '%'
AND a.number = '01'
AND a.code = v_CODE
AND a.ssn_head = v_SSN_HEAD
AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB)
LOOP
bRow_found := TRUE;
EXIT;
END LOOP;
END;
分享并享受。
答案 3 :(得分:0)
您可以使用HAVING
检查COUNT
是否大于1。
CURSOR c_example IS
SELECT COUNT(*)
...
HAVING COUNT(*) > 1;
l_dummy PLS_INTEGER;
OPEN c_example;
FETCH c_example INTO l_dummy;
IF c_example%NOTFOUND THEN
CLOSE c_example;
RETURN FALSE
ELSE
CLOSE c_example;
RETURN TRUE
END IF;
答案 4 :(得分:0)
“第一”是什么意思?没有WHERE子句,您不知道关系数据库存储行的顺序。
您是否有数据表明您存在性能问题,或者您是否过早优化?
我不相信你的想法会导致任何性能提升。我会去别处看看。
从这里开始:
AND TO_CHAR( a.mbr_dob, 'MM/DD/YYYY') = v_DOB;
我认为如果你解析这个,你会发现TO_CHAR会强制Oracle使用TABLE SCAN。在这种情况下,出生日期的任何指数都是无用的。
这会向我建议您已将出生日期列建模为字符串/ VARCHAR。为什么你会这样做?使用DATE列并传入适当的日期变量。您的表现会有所改善,您也会有实际的家庭数量。这对我来说似乎很有用。