2

次のようなSQLクエリを作成しました:

select field1, field2 from table_name;

問題は、このクエリが 100 万件のレコードまたは 10 万件を超えるレコードを返すことです。field1 を含む入力ファイル (約 20,000 から 50,000 レコード) があるディレクトリがあります。これは私が懸念している主なデータです。perl スクリプトを使用して、ディレクトリから抽出しています。しかし、次のようなクエリを書くと:

select field1 , field2 from table_name 
where field1 in (need to write a query to take field1 from directory);

IN 原因を使用すると、1000 エントリの処理に制限があります。IN 原因の制限を克服するにはどうすればよいですか?

4

4 に答える 4

4

どの DBMS でも、それらを一時テーブルに挿入しJOIN、リストのサイズに対する IN 句の制限を回避するために実行します。

例えば

CREATE TABLE #idList
(
    ID INT
)
INSERT INTO #idList VALUES(1)
INSERT INTO #idList VALUES(2)
INSERT INTO #idList VALUES(3)

SELECT * 
FROM 
    MyTable m 
    JOIN #idList AS t 
    ON m.id = t.id

以前のプロジェクトの 1 つである SQL Server 2005 では、別のデータ ストア (lucene インデックス) をクエリした結果であるこの値のリストを XML に変換し、それを SQL クエリで XML 変数として渡し、nodes()XML データ型の関数を使用してテーブルを作成し、それを使用してを実行JOINします。

DECLARE @IdList XML
SELECT @idList = '
<Requests>
    <Request id="1" />
    <Request id="2" />
    <Request id="3" />
</Requests>'

SELECT * 
FROM 
    MyTable m 
    JOIN (
            SELECT id.value('(@id)[1]', 'INT') as 'id' 
            FROM @idList.nodes('/Requests/Request') as T(id)
         ) AS t 
    ON m.id = t.id
于 2012-10-13T13:55:00.933 に答える
1

Vikdor の言うとおりです。IN()句を使用してこれをクエリするべきではありません。テーブルを使用してJOIN.

彼の答えを拡張すると、次のアプローチをお勧めします。

  1. Perl 経由ですべての入力ファイルのリストを取得する
  2. 一意で、すべての入力ファイルに基づくリストのハッシュ値を計算する賢い方法を考えてください (ファイル名などをお勧めします)。
  3. このハッシュは、入力ファイル名を格納するテーブルの名前として機能します (ハッシュが変更されると破棄される準一時テーブルと考えてください)。
  4. JOINそのテーブルが正しいレコードを返す

ステップ 2. では、cronjob を使用するか、クエリが実際に必要になるたびに計算することができます (ただし、応答が遅くなります)。これを正しく行うには、ファイルが追加/削除される可能性を考慮する必要があります。

ステップ 3. では、現在のハッシュ値が前回の実行と異なる場合に以前に生成されたテーブルを削除し、現在のハッシュにちなんで名付けられたテーブルを再作成するロジックが必要です。

準一時テーブル名については、次のようなものをお勧めします

input_files_XXX (.i.e. prefix_<hashvalue>)

これにより、削除する古いテーブルを簡単に知ることができます。

于 2012-10-13T14:17:50.763 に答える
0

Oracleに関しては、一時テーブルを使用する場合の最善の解決策は、インデックスを作成しないとパフォーマンスが低下するため、ネストされたテーブル型を使用することです。

CREATETYPEmy_nttはdirectory_recのテーブルです。

次に、my_nttタイプの変数を返し、クエリで使用する関数f1を作成します。

table1、field2 from table_name where field1 in table(cast(f1 as my_ntt));を選択します。

于 2012-10-13T15:52:35.330 に答える
0

50,000 個の ID を 1000 個の ID の 50 個のリストに分割し、そのようなリストごとにクエリを実行し、結果セットを perl で収集できます。

于 2012-10-13T14:16:05.653 に答える