6

次のような約500万行のテーブルがあります。

Erp_in:

corr_id varchar(50) (almost Unique)
corr_type nvarchar(1) (4 distinct values)
interface varchar(20) (around 10 distinct values)
indate DateTime

3つの異なるインデックス(corr_id、interface、およびindate)を使用して、通常
は元のテーブルと結合したままにしておいた別のテーブルがあり、約100000行あります

Erp_In_failed:

corr_id
interface
error (clob)   
input (clob)

インデックス付き (corr_id およびインターフェイス)

最適化したいクエリは次のようにシンプルです。

SELECT a.corr_id, a.interface, a.indate, b.error 
FROM erp_in a left join erp_in_failed b on a.corr_id = b.corr_id and a.interface =          b.interface
Order by a.indate desc;

order by を削除すると、クエリにそれほど時間はかかりませんが、データの並べ替えには約 3 分かかります。

クエリを最適化するにはどうすればよいですか? 私はパーティショニング/履歴テーブルへの古いデータの削除/おそらくシーケンスの主キーとそれによる順序の作成、またはあなたが念頭に置いている何かについて考えていました...

編集:
実行計画はフルテーブルスキャンを示しており、注文に時間がかかるのは結合ではありません。
このクエリでさえ永遠にかかります:

SELECT * FROM erp_in
ORDER BY indate;

ページングを使用してみましたが、それも機能せず、20 の結果が得られるまでに数分かかります。間違っているのでしょうか?

indate フィールドに WHERE 句を追加すると、インデックスが使用されますが、作成後 20 日未満の場合に限り、それ以外は引き続きフル テーブル スキャンを使用します。(40 日であっても、INDEX ヒントを追加すると、クエリの実行が速くなりましたが、それでも十分ではありません)。

好奇心のために、私は100万行の単純なテーブルを持っています.order byは数秒かかります.違いは何ですか? RAMでソートするには100万で十分ですか?

ありがとう、

4

5 に答える 5

4

約 10 万個の clob を含む 500 万行を並べ替えています。メモリ内でそれを行うことはまずありません。stats をオンにして SQL*Plus でクエリを実行すると、クエリがディスクに大量に書き出されることがわかります。

パフォーマンスを向上させる 1 つの方法は、バッファー キャッシュに GB を追加することですが、これは高価なオプションであり、迅速なオプションではない可能性があります。

erp_in(indate desc, corr_id, interface)駆動テーブルからの結果は事前にソートされるため、順序付けの作業が少なくて済むため、複合インデックスを構築することも役立ちます。INDATE によるパーティショニングでも同様の効果が得られる可能性がありますが、パーティショニングは Enterprise Edition への有料の追加料金であるため、安価な修正ではありません (より多くのメモリを使用すると、おそらくはるかに安くなります)。

古いデータのアーカイブへの言及は、実際にはすべてのレコードを取得したくないことを示唆しています。この場合、WHERE 句を使用して結果セットのサイズを小さくすると、非常に役立ちます。何かを調整する最も簡単な方法は、そもそも仕事をしないことです。

主キーを追加して並べ替えても、実際の並べ替えに必要な労力は減りません。


「では、日付で分割する必要がありますか? INDATE フィールドに WHERE 句を追加しなくても役立ちますか?」

場合によります。パーティショニングにより、テーブルの物理的な編成が導入されるため、(少なくとも) 行の並べ替えが少なくて済みます。どれだけ少なくなるかは、パーティションの粒度に依存します。ある日の範囲でパーティション化すると、テーブルはすでにほぼすでに INDATE 順になっています。1 年の範囲でパーティション化すると、そうではありません。

ただし、パーティショニングは主にパフォーマンス オプションではないことに注意してください。これは、データ、特にロード、および可用性を管理するためのオプションです。実際、一部のクエリ (パーティション キーによって適用される順序に適合しないクエリ) のパフォーマンスが低下する可能性があります。

では、日付で分割する必要がありますか? 私たちが答えられる質問ではありません。それに答えるには、あなたが持っていて、私たちには欠けている、あなたのシステムに関する深い知識が必要です。ただし、ライセンスをお持ちの場合は、調査してベンチマークする必要があるオプションであることは間違いありません。

于 2012-11-01T09:49:21.517 に答える
1

Are you really fetching so many rows to web server? If yes, review your code to narrow down to what's required.

  1. Try archiving old data to another table based on datetime. Re-write logic to fetch older data only when required.
  2. As others have mentioned, indexes / keys should help a mile in most cases

If you can't do any of the above, another ugly solution (not sure if it will not go worse) is to create in-memory table, filter and fetch what's required and then fetch CLOB data.

于 2012-11-01T13:27:28.960 に答える
0

私の経験を共有したいと思います。質問の作成者が言及したのと同様の問題に悩まされていました。

私のクエリは長く、いくつかのテーブルと結合が含まれています。ここでは、単純なクエリを使用してシナリオを紹介しようとしています.約 80,000 レコードが返されます. order by がクエリのボトルネック部分であることがわかりました。

select column1, colum2 from table order by colum2

実行計画を確認したときに、クエリが column1 のインデックスを使用しているように発生していました。

column1 を順番に含めました。

select column1, column2 from table order by column2, column1

それは私を助けました.サンプルの読み取りは、変更前のように8秒かかりましたが、上記の変更後はわずか2秒しかかかりません.

これにはリンクが非常に役立ちます。

于 2017-02-22T12:19:23.403 に答える
0

Have you experimented with additional indexes? I have done something similar and I have used a clustered index on the indate DateTime field. This is on a premise that most queries will be bounded to some time period and that rebalancing of B-trees will not be an issue as most inserts will with increasing key values. Get the execution plan for your query and look if you could not optimize it a bit.

于 2012-11-01T09:05:21.220 に答える
0

(indate desc, corr_id, interface)erp_in に複合インデックスを作成すると、インデックスが使用され、クエリが高速になります。

ただし、並べ替えるデータのサイズを最小限に抑える方法を見つける必要があります。

たとえば、過去 2 日間のみを取得します。

SELECT a.corr_id, a.interface, a.indate, b.error 
FROM erp_in a left join erp_in_failed b 
     on a.corr_id = b.corr_id and a.interface = b.interface
WHERE indate > trunc(sysdate - 1)
Order by a.indate desc;
于 2012-11-01T09:42:32.343 に答える