Oracle で不等号演算子のさまざまな構文のパフォーマンスをテストしました。テストへの外部からの影響をすべて排除しようとしました。
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);
シーケンスを使用して、1,000 万行がテーブルに追加されましSYSDATE
た。タイムスタンプとランダム データは DBMS_RANDOM (AZ) 経由で、(0-99) は他の 2 つのフィールドです。
SELECT COUNT(*) FROM load_test;
COUNT(*)
----------
10000000
1 row selected.
スキーマが分析され、適切な統計が提供されました。
EXEC DBMS_STATS.GATHER_SCHEMA_STATS(ownname => 'LOADTEST', estimate_percent => NULL, cascade => TRUE);
3 つの単純なクエリは次のとおりです。
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
3 つのクエリの実行計画は同じで、タイミングは 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
数百分の 1 秒の変動がありますが、重要ではありません。3 つの構文の選択肢のそれぞれの結果は同じです。
構文の選択は解析され、最適化され、同じ労力で同時に返されます。したがって、このテストでどちらか一方を使用しても、認識できる利点はありません。
「ああ、BC」、「私のテストでは、本当の違いがあると信じており、そうでなければそれを証明することはできません」とあなたは言います.
はい、私は言います、それは完全に真実です。テスト、クエリ、データ、または結果を表示していません。だから私はあなたの結果について何も言うことはありません。他のすべての条件が同じであれば、どの構文を使用しても問題ないことを示しました。
「では、テストで 1 つの方が優れていることがわかるのはなぜですか?」
良い質問。いくつかの可能性があります:-
- テストに欠陥があります (外部要因 (他のワークロード、キャッシュなど) を排除していません。十分な情報に基づいて決定できる情報が提供されていません)
- あなたのクエリは特殊なケースです (クエリを見せてください。それについて話し合うことができます)。
- あなたのデータは特殊なケースです (おそらく - しかし、どのように - 私たちにもそれはわかりません)。
- 外部からの影響は他にもあります。
文書化された反復可能なプロセスを通じて、ある構文を使用しても別の構文を使用してもメリットがないことを示しました。<> != と ^= は同義だと思います。
そうでなければ大丈夫だと思うなら、そう
a)自分で試すことができる文書化された例を示します
と
b) 最適と思われる構文を使用します。私が正しくて違いがなければ、それは問題ではありません。あなたが正しければ、クールであれば、ほんの少しの作業で改善が得られます。
「でも、バーレソンはそのほうがましだと言ったし、私はファロート、ルイス、カイト、その他のバカよりも彼を信頼している」
彼はそれが良いと言ったのですか?私はそうは思わない。彼は決定的な例、テスト、または結果を提供しませんでしたが、!= の方が優れていると言っている人にリンクし、投稿の一部を引用しただけです。
言わずに見せる。