场景: 在Oracle数据库中,此SQL慢得多:
SELECT *
FROM TBL_MAIN A, TBL_CHILD_1 B, TBL_CHILD_2 C, TBL_CHILD_3 D, TBL_CHILD_4 E
WHERE A.ID_MAIN = B.ID_MAIN
AND A.ID_MAIN = C.ID_MAIN
AND A.ID_MAIN = D.ID_MAIN
AND A.ID_MAIN = E.ID_MAIN;
比那
SELECT *
FROM TBL_MAIN X, TBL_CHILD_1 B, TBL_CHILD_2 C, TBL_CHILD_3 D, TBL_CHILD_4 E
WHERE X.ID_MAIN = B.ID_MAIN
AND X.ID_MAIN = C.ID_MAIN
AND X.ID_MAIN = D.ID_MAIN
AND X.ID_MAIN = E.ID_MAIN;
换句话说,如果我使用“ A”作为“ TBL_MAIN”表的别名,则当我连接了3个或更多表时,这将导致查询速度变慢。
当我在内部联接中使用表“ TBL_MAIN” AS“ A”添加更多表时,情况变得最糟。
发生了什么事?
答案 0 :(得分:3)
是的。它是一元收集运算符“ IS A SET”的一部分。在Oracle中,它有点复杂,为了保证向后兼容性,Oracle具有“保留字”和“关键字”。其中的一个不能用作标识符,而另一些可能具有特殊含义的是某些上下文-但仍可以用作标识符。
例如,您仍然可以像使用SQL
select * from commit;
or
select * from join where X is a set;
诸如提交,联接,模型之类的词仍然可以用作标识符。
当然这不会影响SQL评估的速度。特别是在游标被重用时。这可能只会减慢解析速度。
答案 1 :(得分:2)
我发现X
实际上比A
快,但是Z
甚至更慢:
Alias A 60.257 seconds
Alias X 57.747 seconds
Alias Y 58.383 seconds
Alias Z 62.157 seconds
说实话,这些差异很小,无法证明别名之间的差异。
我用5个大表(tbl_main 2200万,tbl_child 1700万等)对其进行了测试。然后将SELECT *
更改为SELECT COUNT(*)
,以确保所有行都已处理。将忽略第一次执行以预热缓存。接下来的三轮是平均。
DECLARE
FUNCTION test1(c VARCHAR2) RETURN NUMBER IS
time1 NUMBER; time2 NUMBER; stmt VARCHAR2(3000); n NUMBER;
BEGIN
stmt := q'!
SELECT count(*)
FROM tbl_main #, tbl_child1 B, tbl_child2 C, tbl_child3 D, tbl_child4 E
WHERE #.geb_id = B.geb_id
AND #.geb_id = C.geb_id
AND #.geb_id = D.geb_id
AND #.geb_id = E.geb_id
!';
stmt := REPLACE(stmt, '#', c);
--dbms_output.put_line(stmt);
time1 := dbms_utility.get_time();
EXECUTE IMMEDIATE stmt INTO n;
time2 := dbms_utility.get_time();
return (time2-time1)/100;
END test1;
PROCEDURE test3(c VARCHAR2) IS
ignore NUMBER; seconds NUMBER;
BEGIN
ignore := test1(c);
seconds := (test1(c)+test1(c)+test1(c)) / 3;
DBMS_OUTPUT.PUT_LINE('Alias '||c||' '||round(seconds,3)||' seconds');
END test3;
BEGIN
test3('A');
test3('X');
test3('Y');
test3('Z');
END;
/
答案 2 :(得分:2)
是的。在12c。
SELECT KEYWORD
FROM V$RESERVED_WORDS
WHERE KEYWORD = 'A'
;
答案 3 :(得分:0)
简答号。 A不是保留字。如果它是保留字,则会引发错误。但是,要分析性能问题,您需要发布指标以执行查询。
答案 4 :(得分:0)
问题解决了! 现在,两个SQL具有相同的时间,就像@wolφi所说的那样快一点。
这种情况持续了两天,但现在已经正常了。
我相信在关闭数据库后,数据库会恢复正常。
一个有趣的事情是,当问题发生时,SQL Tuning Advisor提出了使正常工作的SQL的执行计划(加快了99.9%)。不幸的是,我当时没有保存推荐报告以在此处显示。
但是现在没有任何有效的SQL配置文件,这些SQL具有相同的时间。