字符 "A" 是 Oracle 数据库中的保留关键字吗?

Is the character "A" a reserved keyword in Oracle Database?

场景: 在 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;

换句话说,当我有 3 个或更多 table 加入时,如果我使用 "A" 作为 "TBL_MAIN" table 的别名,它会导致速度变慢询问。

当我在 table "TBL_MAIN" AS "A".

的内部连接中添加更多 table 时,情况变得最糟

发生了什么事?

简答不。 A 不是保留字。如果它是保留字,则会引发错误。但是,要分析您的性能问题,您需要 post 查询执行的指标。

我发现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_child1700 万等)对其进行了测试。我将 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;
/

是的。它在 12c.

SELECT KEYWORD
FROM V$RESERVED_WORDS
WHERE KEYWORD = 'A'
;

是的。它是一元集合运算符 "IS A SET" 的一部分。在Oracle中有点复杂,为了保证向后兼容Oracle有"reserved words"和"keywords"。其中之一不能用作标识符,而其他可能在某些上下文中具有特殊含义 - 但仍然可以用作标识符。

例如,您仍然可以像

一样使用SQL
select * from commit;
or
select * from join where X is a set;

commit、join、model 等词仍然可以用作标识符。

当然这不能影响SQL评价的速度。特别是当光标被重用时。它可能只会减慢解析速度。

问题自行解决! 现在两个 SQL 时间相同,只是像@wolφi 说的快了一点。

这种情况持续了两天,现在正常了。

我相信关闭后数据库就正常了。

关于此的一件有趣的事情是当问题发生时,SQL Tuning Advisor 为 SQL 提出了一个执行计划,他们使工作正常(快 99.9%)。遗憾的是,我当时没有保存推荐报告来显示这里。

但现在没有任何 SQL 配置文件处于活动状态,SQL 的配置文件处于同一时间。