1

以下の SQL を用意しましたが、応答時間が許容範囲を超えています。

これは、RPG プログラムの DECLARE、PREPARE、OPEN、および FETCH で使用されます。ここでは、選択されたフィールドがホスト変数に配置され、配列に取り込まれ、サブファイル表示のた​​めに [降順] に並べ替えられます。

使用中の 2 つのテーブルはまったくキー付けされておらず (PF)、以下の WHERE 句に示すように結合されています。

Select DISTINCT B.Fld1, B.Fld2, B.Fld3, B.Fld4,
A.Fld1, A.Fld2, A.Fld3, A.Fld4, A.Fld5, A.Fld6, A.Fld7, A.Fld8, A.Fld9
From TableA A, TableB B
Where A.Fld2 = B.Fld5
And A.Fld1 = B.Fld6 || B.Fld7
And ((A.Fld7 BETWEEN <from-date> and <to-date>)
Or (A.Fld5 BETWEEN <from-date> and <to-date>))

これを「真の」左結合として書き直しましたが、改善はありません。

また、A.Fld2 と A.Fld1 をキーとして 2 つの利用可能な LF を使用しましたが、わずかに改善されています。

再帰的 SQL でうまくいくと思いますが、それを実現する経験がありません。各テーブルからの選択を作成し、それ自体で必要に応じて機能させます。私が望む結果を得るために、それらを 1 つの美しい獣にまとめる方法がわかりません。

この結果セットは 1 週間で約 10,000 行であり、2 週間分が必要です。

TableA には約 6,000,000 のレコードがあり、TableB には約 160,000 のレコードがあります。

今のところ、ロジックは

  1. 上記の前に単純な SQL を実行します。
  2. レコードをカーソルで移動し、配列に入力します
  3. 上記の SQL を実行します。
  4. レコードをカーソルで移動し、同じ配列に追加します
  5. 配列をソートし、それを使用してサブファイルにデータを取り込みます。

デバッグでは、上記の SQL が問題の本質であることを確認しました。

真実は、サブファイルを作成するために 1 つの結果テーブルに結合できると思われる 3 つのファイルがあるということです。上記のクエリを通過できる場合は、「できると思います」が他のファイルの結合を処理します。

私の推測では、「これを打ち負かす」ことができる人がそこにいると思います! 私はかつて彼と一緒に働いたことがあります!

これは RPG ではありません。システムに関する質問です。以前、RPG でこのような SQL を作成したことがあります。問題は、他の誰かが SQL を書いたことです。: (

4

4 に答える 4

0

結合のOR(または||)ステートメントでパフォーマンスの問題が発生しています。おそらくBETWEEN(DATETIMEではうまく機能していません)からです。「Or」と「||」の両方を削除します ステートメントではなく、「UNIONALL」を間に挟んだ4つの個別のクエリがあります。直感に反しているように見えても、パフォーマンスが大幅に向上します。また、その日付を[date]>fromDateと[date]に設定します


UPDATE-これはOR句のない完全なクエリです。> / <記号は読みづらくなる可能性があるため、最初にコーヒーを飲んでください。

Select DISTINCT B.Fld1, B.Fld2, B.Fld3, B.Fld4,
A.Fld1, A.Fld2, A.Fld3, A.Fld4, A.Fld5, A.Fld6, A.Fld7, A.Fld8, A.Fld9
From TableA A, TableB B
Where A.Fld2 = B.Fld5
And A.Fld1 = B.Fld6
And A.Fld7 > <from-date> 
AND A.Fld7 < <to-date>
AND A.Fld5 < <from-date> -- Excluding these to avoid duplicates
and A.Fld5 > <to-date> -- Excluding these to avoid duplicates
UNION ALL
Select DISTINCT B.Fld1, B.Fld2, B.Fld3, B.Fld4,
A.Fld1, A.Fld2, A.Fld3, A.Fld4, A.Fld5, A.Fld6, A.Fld7, A.Fld8, A.Fld9
From TableA A, TableB B
Where A.Fld2 = B.Fld5
And A.Fld1 = B.Fld6
AND A.Fld5 > <from-date> 
and A.Fld5 < <to-date>
UNION ALL
Select DISTINCT B.Fld1, B.Fld2, B.Fld3, B.Fld4,
A.Fld1, A.Fld2, A.Fld3, A.Fld4, A.Fld5, A.Fld6, A.Fld7, A.Fld8, A.Fld9
From TableA A, TableB B
Where A.Fld2 = B.Fld5
And A.Fld1 = B.Fld7
And A.Fld7 > <from-date> 
AND A.Fld7 < <to-date>
AND A.Fld5 < <from-date> -- Excluding these to avoid duplicates
and A.Fld5 > <to-date> -- Excluding these to avoid duplicates
UNION ALL
Select DISTINCT B.Fld1, B.Fld2, B.Fld3, B.Fld4,
A.Fld1, A.Fld2, A.Fld3, A.Fld4, A.Fld5, A.Fld6, A.Fld7, A.Fld8, A.Fld9
From TableA A, TableB B
Where A.Fld2 = B.Fld5
And A.Fld1 = B.Fld7
AND A.Fld5 > <from-date> 
and A.Fld5 < <to-date>
于 2012-04-18T20:01:06.760 に答える
0

where 句の各句を括弧で囲むこともできます。それ以外の:

Where A.Fld2 = B.Fld5 And A.Fld1 = B.Fld6 || B.Fld7 And ((A.Fld7 BETWEEN <from-date> and <to-date>) Or (A.Fld5 BETWEEN <from-date> and <to-date>)) 

Where (A.Fld2 = B.Fld5) And ((A.Fld1 = B.Fld6) || B.Fld7) And ((A.Fld7 BETWEEN <from-date> and <to-date>) Or (A.Fld5 BETWEEN <from-date> and <to-date>))

問題は || の優先順位です。オペレーター。AND と同じ場合は、基本的に次のことを行っています。

WHERE (A.Fld2 = B.fld5) or B.fld7

AND の後に「or」が優先されるため、クロス ジョインが発生します。. . パフォーマンスが非常に悪くなります。

于 2012-04-18T20:41:03.613 に答える
0

これを試して

Select DISTINCT B.Fld1, B.Fld2, B.Fld3, B.Fld4,
A.Fld1, A.Fld2, A.Fld3, A.Fld4, A.Fld5, A.Fld6, A.Fld7, A.Fld8, A.Fld9
From 
(
select * from TableA where ((Fld7 BETWEEN <from-date> and <to-date>)
Or (Fld5 BETWEEN <from-date> and <to-date>))
) A, 
TableB B
Where A.Fld2 = B.Fld5
And A.Fld1 = B.Fld6 || B.Fld7

この

Select DISTINCT c.Fld1, c.Fld2, c.Fld3, c.Fld4,
c.Fld1, c.Fld2, c.Fld3, c.Fld4, c.Fld5, c.Fld6, c.Fld7, c.Fld8, c.Fld9
From 
(
select * from TableA A, TableB B
Where A.Fld2 = B.Fld5
And A.Fld1 = B.Fld6 || B.Fld7
)c
where ((c.Fld7 BETWEEN <from-date> and <to-date>)
Or (c.Fld5 BETWEEN <from-date> and <to-date>))

そのうちの少なくとも 1 つが高速になることを願っています。

編集

ここでは、日付の比較が問題であるため、結合がボトルネックまたはテーブルスキャンのいずれかです。したがって、最初に必要な行を抽出してから、結合または日付比較でさらに処理するという考え方です。これにより、番号が制限されます。行のテーブル全体を処理するのではなく、処理が必要な合計行数。

于 2012-04-18T20:19:55.860 に答える
0

指定された SELECT ステートメントに基づいて、TableA からクエリを開始します。これは、Fld7 と Fld5 の日付/タイムスタンプ値に基づいてエントリを取得する場所であるためです。まず、これら 2 つの列にインデックスを作成します。どちらも独自のインデックスが必要です。

最初に、TableA からデータを取得するパフォーマンスを確認する必要があります。これを行うには、SELECT ステートメントを実行します。

SELECT COUNT(*)
  FROM TableA
 WHERE 
   (A.Fld7 BETWEEN <from-date> and <to-date>) OR
   (A.Fld5 BETWEEN <from-date> and <to-date>)

これで十分なパフォーマンスが得られない場合、問題は TableA のインデックス作成にあります。これらのインデックスに INCLUDE 定義を持つ他の列を追加することも検討できます。おそらく、少なくとも TableB に結合するために使用するフィールド Fld1 と Fld2 です。

TableA で十分なパフォーマンスが得られたら、TableB に効率的に結合できるようにする必要があります。A.Fld1 = B.Fld6 || B.Fld7見た目はかなり問題あり。 これが TableB 内で比較的ユニークであることを願ってB.Fld5います。その場合、TableB に Fld5 のインデックスがあれば十分です。A.Fld1 チェックは、 join で得られる少量の行を除外するためだけに join に含まれますA.Fld2 = B.Fld5

B.Fld5 が比較的ユニークでない場合、問題が発生します :) その場合、結合で次のようなものを試してみてください。

SELECT ... 
FROM TableA A, TableB B
WHERE
   A.Fld2 = B.Fld5 AND
   SUBSTR(A.Fld1, 1, N) = B.Fld6 AND
   A.Fld1 = B.Fld6 || B.Fld7
...

アイデアは、連結されたときに A.Fld1 に一致する TableB の行から検索するのではなく、A.Fld1 から部分文字列を取得して、B.Fld6 に一致するようにすることです。その後、B.Fld6 に適切なインデックスがあり、TableB で実際に一意であることを確認する必要があります。明らかにそれを拡張して、B.Fld7 に同じパターンを適用できます。つまり、次のようになります。

SELECT ... 
FROM TableA A, TableB B
WHERE
   A.Fld2 = B.Fld5 AND
   SUBSTR(A.Fld1, 1, N) = B.Fld6 AND
   SUBSTR(A.Fld1, N, LENGTH(A.Fld1)) = B.Fld7
...

上記の JOIN では、B.Fld5、B.Fld6、および B.Fld7 から最も選択的な値で始まる TableB のインデックスがあれば十分な場合があります。

HTH。

于 2012-04-18T20:06:03.160 に答える