복붙노트

[SQL] 오라클 <>,! =, ^ = 운영

SQL

오라클 <>,! =, ^ = 운영

나는 그 사업자의 차이, 주로 자신의 성능 차이를 알고 싶어요.

나는 <> 및! = SQL, 그것은 더 성능 관련 정보가 없습니다 차이를 살펴 있었다.

그럼, dba-oracle.com에 발견 그것은 10.2 이후 성능이 매우 다를 수 있음을 시사한다.

내가 왜 궁금해? ! = 항상 <> 다음 더 잘 수행 하는가?

<>까지 변화 라이브 시스템 쇼에 우리의 테스트 및 성능 = 쿼리가 돌아올 시간에 큰 영향을 미친다 나는 이런 일이 왜 그들이 동일하거나하지 여부를 물어 여기입니다 : 참고!.. 나는 그들이 의미 알고 있지만, 현실에서 그들은 다르다.

해결법

  1. ==============================

    1.나는 오라클에서 동일하지 운영자의 다른 구문의 성능을 테스트했습니다. 나는 시험에 대한 모든 외부의 영향을 제거하기 위해 노력했다.

    나는 오라클에서 동일하지 운영자의 다른 구문의 성능을 테스트했습니다. 나는 시험에 대한 모든 외부의 영향을 제거하기 위해 노력했다.

    나는 11.2.0.3 데이터베이스를 사용하고 있습니다. 다른 세션이 연결되지 않고 데이터베이스 테스트를 시작하기 전에 다시 시작되었습니다.

    스키마는 단일 테이블과 기본 키 순서로 작성

    CREATE TABLE loadtest.load_test (
      id NUMBER NOT NULL,
      a VARCHAR2(1) NOT NULL,
      n NUMBER(2) NOT NULL,
      t TIMESTAMP NOT NULL
    );
    
    CREATE SEQUENCE loadtest.load_test_seq
    START WITH 0
    MINVALUE 0;
    

    테이블은 쿼리의 성능을 향상시키기 위해 색인되었다.

    ALTER TABLE loadtest.load_test
    ADD CONSTRAINT pk_load_test
    PRIMARY KEY (id)
    USING INDEX;
    
    CREATE INDEX loadtest.load_test_i1
    ON loadtest.load_test (a, n);
    

    천만 행은 다른 두 필드 DBMS_RANDOM (A-Z) 및 (0-99)을 통해 임의의 타임 스탬프와 데이터의 순서 SYSDATE를 사용하여 테이블에 첨가 하였다.

    SELECT COUNT(*) FROM load_test;
    
    COUNT(*)
    ----------
    10000000
    
    1 row selected.
    

    스키마는 좋은 통계를 제공하기 위해 분석 하였다.

    EXEC DBMS_STATS.GATHER_SCHEMA_STATS(ownname => 'LOADTEST', estimate_percent => NULL, cascade => TRUE);
    

    세 가지 간단한 쿼리는 다음과 같습니다 -

    SELECT a, COUNT(*) FROM load_test WHERE n <> 5 GROUP BY a ORDER BY a;
    
    SELECT a, COUNT(*) FROM load_test WHERE n != 5 GROUP BY a ORDER BY a;
    
    SELECT a, COUNT(*) FROM load_test WHERE n ^= 5 GROUP BY a ORDER BY a;
    

    이들은 (다만, <>와! = 또한 ^ =)과 정확히 같지 않음 연산자 구를 제외한 동일

    먼저 각 쿼리 캐싱의 효과를 제거하기 위해 결과를 수집하지 않고 실행됩니다.

    다음 타이밍과 자동 추적 쿼리의 실제 실행 시간과 실행 계획을 모두 수집에 전환했다.

    SET TIMING ON
    
    SET AUTOTRACE TRACE
    

    이제 쿼리를 다시 실행됩니다. 첫번째로는 <>입니다

    > SELECT a, COUNT(*) FROM load_test WHERE n <> 5 GROUP BY a ORDER BY a;
    
    26 rows selected.
    
    Elapsed: 00:00:02.12
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2978325580
    
    --------------------------------------------------------------------------------------
    | Id  | Operation             | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |              |    26 |   130 |  6626   (9)| 00:01:20 |
    |   1 |  SORT GROUP BY        |              |    26 |   130 |  6626   (9)| 00:01:20 |
    |*  2 |   INDEX FAST FULL SCAN| LOAD_TEST_I1 |  9898K|    47M|  6132   (2)| 00:01:14 |
    --------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - filter("N"<>5)
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
          22376  consistent gets
          22353  physical reads
              0  redo size
            751  bytes sent via SQL*Net to client
            459  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
             26  rows processed
    

    다음! =

    > SELECT a, COUNT(*) FROM load_test WHERE n != 5 GROUP BY a ORDER BY a;
    
    26 rows selected.
    
    Elapsed: 00:00:02.13
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2978325580
    
    --------------------------------------------------------------------------------------
    | Id  | Operation             | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |              |    26 |   130 |  6626   (9)| 00:01:20 |
    |   1 |  SORT GROUP BY        |              |    26 |   130 |  6626   (9)| 00:01:20 |
    |*  2 |   INDEX FAST FULL SCAN| LOAD_TEST_I1 |  9898K|    47M|  6132   (2)| 00:01:14 |
    --------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - filter("N"<>5)
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
          22376  consistent gets
          22353  physical reads
              0  redo size
            751  bytes sent via SQL*Net to client
            459  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
             26  rows processed
    

    마지막으로 ^ =

    > SELECT a, COUNT(*) FROM load_test WHERE n ^= 5 GROUP BY a ORDER BY a;
    
    26 rows selected.
    
    Elapsed: 00:00:02.10
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 2978325580
    
    --------------------------------------------------------------------------------------
    | Id  | Operation             | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
    --------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT      |              |    26 |   130 |  6626   (9)| 00:01:20 |
    |   1 |  SORT GROUP BY        |              |    26 |   130 |  6626   (9)| 00:01:20 |
    |*  2 |   INDEX FAST FULL SCAN| LOAD_TEST_I1 |  9898K|    47M|  6132   (2)| 00:01:14 |
    --------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       2 - filter("N"<>5)
    
    
    Statistics
    ----------------------------------------------------------
              0  recursive calls
              0  db block gets
          22376  consistent gets
          22353  physical reads
              0  redo size
            751  bytes sent via SQL*Net to client
            459  bytes received via SQL*Net from client
              3  SQL*Net roundtrips to/from client
              1  sorts (memory)
              0  sorts (disk)
             26  rows processed
    

    세 개의 질의 실행 계획은 동일한 타이밍 및 2.12, 2.13 및 2.10 초.

    쿼리에 사용되는 중 구문은 주목해야한다 실행 계획을 항상 표시 <>

    시험은 각 오퍼레이터 구문 반복하여 10 회 행 하였다. 다음은 타이밍입니다 -

    <>
    
    2.09
    2.13
    2.12
    2.10
    2.07
    2.09
    2.10
    2.13
    2.13
    2.10
    
    !=
    
    2.09
    2.10
    2.12
    2.10
    2.15
    2.10
    2.12
    2.10
    2.10
    2.12
    
    ^=
    
    2.09
    2.16
    2.10
    2.09
    2.07
    2.16
    2.12
    2.12
    2.09
    2.07
    

    두 번째의 몇 백분의 몇 가지 차이가있는 동안 그것은 중요하지 않습니다. 세 구문 선택 각각에 대한 결과는 동일하다.

    구문 선택은, 구문 분석 최적화와 같은 시간에 같은 노력으로 반환된다. 이 테스트에서 다른 이상을 사용하는 띄는 장점 때문에이 없습니다.

    "아 BC는"당신은 "내 테스트에서 내가 거기에 진정한 차이는 당신이 그렇지 않으면 그것을 증명할 수 있다고 생각합니다"라고.

    네, 완벽하게 사실이다,라고. 당신은 당신의 검사 결과, 쿼리, 데이터 나 결과를 표시하지 않았습니다. 나는 당신의 결과에 대해 할 말이 아무것도 그래서. 나는 다른 모든 조건이 동일하여, 당신이 사용하는 구문 어떤 문제가되지 않습니다 것으로 나타났습니다.

    "왜 나는 그 사람이 내 테스트에서 더 볼 수 있습니까?"

    좋은 질문. 거기에 몇 가지 가능성 : -

    나는 다른 통해 하나의 구문을 사용하여 얻을 수있는 이점이 없다는 것을 문서화하고 반복 과정을 통해 보여 주었다. 내가 믿을 <>! = 및 ^ = 동의어입니다.

    당신이 그렇지 않으면 잘 믿는다면, 그래서

    A) 나 자신을 시도 할 수있는 문서화 된 예를 보여

    b)는 당신이 최고라고 생각 구문을 사용합니다. 내가 올바른 오전 그것은 중요하지 않습니다 차이가없는 경우. 당신이 올바른 다음 차가운 경우에, 당신은 아주 약간의 작업에 대한 개선이있다.

    "그러나 Burleson의 그것이 더 좋았다 내가 더, Faroult, 루이스, 카이트와 모든 다른 부랑자보다는 그를 신뢰했다."

    그는 그것이 더 좋았다라고 했나요? 그렇게 생각하지 않아요. 그는 어떤 명확한 예를 들어, 테스트를 제공하거나 결과 만 누군가가 그 말에 연결하지 않았다! = 더 나은 한 후 자신의 게시물의 일부를 인용했다.

    쇼는 말하지 않는다.

  2. ==============================

    2.당신은 Burleson의 사이트에서 문서를 참조합니다. 당신은 오라클-L 아카이브 링크를 따라나요? 그리고 당신은 Burleson의이 인용 이메일에 회신 다른 이메일을 읽을습니까?

    당신은 Burleson의 사이트에서 문서를 참조합니다. 당신은 오라클-L 아카이브 링크를 따라나요? 그리고 당신은 Burleson의이 인용 이메일에 회신 다른 이메일을 읽을습니까?

    나는 그렇지 않으면 당신은이 질문을하지 않았을, 당신이 한 생각하지 않습니다. 간의 기본적인 차이가 없기 때문에! =와 <>. 원래 관찰 거의 확실 데이터베이스의 주위 조건에 의해 초래 우연이었다. 자세한 내용을 이해하는 조나단 루이스와 스테판 Faroult의 응답을 읽습니다.

    점까지. 우리가 거리에서 낯선 사람을 만날 때 다음 물론 우리는 정중해야한다 존중을 취급합니다.

    하지만 낯선 사람이 날에 특정의 방법으로 내 데이터베이스 응용 프로그램을 설계하고자하는 경우 "성능을 향상"그들은 그것을 뒷받침 할 설득력있는 설명과 약간의 방탄 테스트 케이스를 가져야한다. 어떤 임의의 개인에서 고립 된 일화는 충분하지 않습니다.

  3. ==============================

    3.기사의 저자는 책의 저자 및 유용한 정보의 납품 있지만, 정확성에 대한 좋은 평판을 가지고 있지 않습니다. 이 경우 문서에서는 잘 알려진 오라클 메일 링리스트에 한 사람의 관찰의 언급에 불과했다. 당신은 응답을 통해 읽는다면 당신은 도전 게시물의 가정하지만, 정확도 어떤 가정을 볼 수 있습니다. 여기에 몇 가지 발췌은 다음과 같습니다 :

    기사의 저자는 책의 저자 및 유용한 정보의 납품 있지만, 정확성에 대한 좋은 평판을 가지고 있지 않습니다. 이 경우 문서에서는 잘 알려진 오라클 메일 링리스트에 한 사람의 관찰의 언급에 불과했다. 당신은 응답을 통해 읽는다면 당신은 도전 게시물의 가정하지만, 정확도 어떤 가정을 볼 수 있습니다. 여기에 몇 가지 발췌은 다음과 같습니다 :

    조나단 루이스는 오라클 지역 사회에서 존경받는 전문가이다.

    .

    .

    .

    다음 응답은 원래 포스터에서입니다.

    .

    .

    .

    .

    이 시점에서 스레드 다이는 그리고 우리는 OP 하나에 해당되지 않았거나 더 이상 조사를하지 않았다 그들이 만든 한 가정을 발견 믿고 날 리드 원래 포스터에서 더 이상 게시물을 볼 수 없습니다.

    나는 또한 당신이 할 계획이나 자동 추적을 설명하는 경우, 당신은 비교가 항상 <>로 표시되는 것을 볼 수 있다고 지적한다.

    여기에 몇 가지 테스트 코드입니다. 만약 당신이 좋아하면 루프 반복 횟수를 늘립니다. 당신은 한면을 볼 수 있습니다 또는 다른 서버 활동에 다른 활동에 따라 더 높은 숫자를 얻을 수 있지만, 어떠한 방식으로 하나의 운영자가 다른보다 더 지속적으로 나올 볼 수 있습니다.

    DROP TABLE t1;
    DROP TABLE t2;
    CREATE TABLE t1 AS (SELECT level c1 FROM dual CONNECT BY level <=144000);
    CREATE TABLE t2 AS (SELECT level c1 FROM dual CONNECT BY level <=144000);
    
    SET SERVEROUTPUT ON FORMAT WRAPPED
    
    DECLARE
       vStart  Date;
       vTotalA Number(10) := 0;
       vTotalB Number(10) := 0;
       vResult Number(10);
    BEGIN   
       For vLoop In 1..10 Loop
          vStart := sysdate;
          For vLoop2 In 1..2000 Loop
             SELECT count(*) INTO vResult FROM t1 WHERE t1.c1 = 777 AND EXISTS
                (SELECT 1 FROM t2 WHERE t2.c1 <> 0);
          End Loop;
          vTotalA := vTotalA + ((sysdate - vStart)*24*60*60);
    
          vStart := sysdate;
          For vLoop2 In 1..2000 Loop
             SELECT count(*) INTO vResult FROM t1 WHERE t1.c1 = 777 AND EXISTS
                (SELECT 1 FROM t2 WHERE t2.c1 != 0);
          End Loop;
          vTotalB := vTotalB + ((sysdate - vStart)*24*60*60);
    
          DBMS_Output.Put_Line('Total <>: ' || RPAD(vTotalA,8) || '!=: ' || vTotalB);
          vTotalA := 0;
          vTotalB := 0;
       End Loop;
    
    END;
    
  4. ==============================

    4.프로그래머가 사용합니다! =

    프로그래머가 사용합니다! =

    DBA는 <> 사용

    다른 실행 계획이있는 경우 각 표기법에 대한 쿼리 캐시의 차이 또는 통계가 있다고 할 수있다. 하지만 난 정말 그렇게 생각하지 않습니다.

    편집하다:

    나는 위의 무엇을 의미. 복잡한 데이터베이스에서 이상한 부작용이있을 수 있습니다. 나는 오라클 좋은의 충분한 모르겠지만, 나는 쿼리 컴파일 캐시는 SQL Server 2008 R2의 같은 있다고 생각합니다. 쿼리는 새 쿼리로 컴파일하는 경우, 데이터베이스 최적화는 현재의 통계에 따라 새로운 실행 계획을 계산합니다. 통계 그것이 다른 발생합니다 변경된 경우, 나쁜 계획 할 수있다.

  5. from https://stackoverflow.com/questions/12003127/oracle-operators by cc-by-sa and MIT license