1

私は問題があります。約 8,000 万から 1 億のレコードを含むテーブルがあります。そのテーブルには、3 から 16 までの異なる「組み合わせ」(varchar) を格納したフィールドがあります。組み合わせは、4 桁の数字、コロン、文字 (AE)、. 例: '0001:A/0002:A/0005:C/9999:E'. この場合、4 つの異なる組み合わせがあります (最大 16 まで可能)。このフィールドはテーブルのすべての行にあり、null になることはありません。

ここでの問題: テーブルを調べて、すべての行を見つけて、それらが類似しているかどうかを確認する必要があります。行の例:

0001:A/0002:A/0003:C/0005:A/0684:A/0699:A/0701:A/0707:A/0709:A/0710:D/0711:C/0712:A/0713:A
0001:A/0002:A/0003:C
0001:A/0002:A/0003:A/0006:C
0701:A/0709:A/0711:C/0712:A/0713:A

ご覧のとおり、これらの各行は (ある意味で) 他の行と似ています。ここで行う必要があるのは、'0001:A/0002:A/0003:C'プログラム (または SQL のパラメーター) を介して送信するときに、すべての行をチェックし、同じ「グループ」があるかどうかを確認することです。ここでの問題は、両方の方法で実行する必要があり、「すばやく」実行する必要があり、SQL でそれらを何らかの方法で比較する必要があることです。

したがって、送信'0001:A/0002:A/0003:C/0005:A/0684:A/0699:A/0701:A/0707:A/0709:A/0710:D/0711:C/0712:A/0713:A'すると、3〜16個の同じ組み合わせがあるすべてのフィールドを見つけて、行を返す必要があります。この 3-16 はパラメーターで指定できますが、最初のパラメーターとして'0002:A:/0711:C/0713:A'send を送信できるため、考えられるすべての組み合わせを見つける必要があるという問題があります。0002:A

ただし、組み合わせは文字列の任意の場所にある可能性があり、「添付」されていないさまざまな組み合わせを送信できるため、インデックスを作成することはできません (途中に別の組み合わせがある可能性があります)。

したがって、送信'0001:A/0002:A/0003:C/0005:A/0684:A/0699:A/0701:A/0707:A/0709:A/0710:D/0711:C/0712:A/0713:A'は同じ 3 ~ 16 フィールドを持つすべてのフィールドを返す必要があり、「0001:A/0002:A/0003:C」を送信する場合は、上の行 + 同様の行を見つける必要があります。 (すべてのパラメータを含むすべて)。

私が試したいくつかのこと/オプション:

  • すべての送信の組み合わせに対して LIKE を実行するのは現実的ではありません + 遅すぎます
  • フィールドのフルインデックス検索を行うことはオプションではありません (正確な理由はわかりません)
  • 機能する可能性のある数少ないことの1つは、フィールドの「ハッシュ」タイプのエンコードを作成し、プログラムを介してそれを計算し、すべて同じ「ハッシュ」を検索することです(ハッシュが同様のテキストに対して異なる組み合わせを生成します。おそらく、そのために正確に記述されるハッシュがいくつかあります
  • 新しいフィールドを作成し、すべての可能な組み合わせを計算/書き込み(挿入時に実行できます)し、組み合わせの割合が同じかどうかをSQL /プログラムを介してチェックしますが、10080の組み合わせを保存する方法がわかりません(16の場合) )効果的に「varchar」に変換するか、ハッシュコードを介して+それらのどれがよく知られているかを知っています。

別の問題があります。このテーブルはほぼ 24 時間年中無休で使用されています。テーブルが大きすぎるため SQL で同じかどうかを確認するために組み合わせを行うのは遅すぎます。プログラムなどを介して行うことができますが、私はしません。これを新しい行に保存する方法についての手がかりがあり、それらが同じであることを何とか知っています。組み合わせを計算し、行の挿入ごとにハッシュコードまたは何かを介してそれらを保存し、プログラムを介して「ハッシュ」を計算し、次のようなテーブルをチェックする可能性があります。

SELECT * FROM TABLE WHERE ROW = "a346adsad"

パラメータはプログラム経由で送信されます。このスクリプトは、チェックが必要なテーブルへの新しい挿入がある可能性があるため、1 分未満で非常に高速に実行する必要があります。

これの要点は、SQL に類似の組み合わせが既に存在するかどうかを確認し、挿入に「類似」する新しい組み合わせをブロックすることです。

私はその問題に3日間対処してきましたが、解決策はありません。最も近いのは、さまざまなタイプの挿入/ハッシュのようなものですが、どのように機能するかわかりません。

可能性のある助けを事前にありがとう、またはこれが可能である場合でも!

4

4 に答える 4

2

したがって、基本的には、1 分以内に8000 万から1 億行の複雑な文字列操作を実行する必要があります。ははは、いいやつ!

ちょっと待って、あなたは真剣です。

これらの検索をその場で行うことは期待できません。その理由を理解するには、Joel Spolsky の基本に戻ることに関する記事を読んでください。

あなたがする必要があるのは、それらの 8000 万から 10000 万の文字列を独自のテーブルにハイブオフし、それらの個別のトークンに'0001:A/0002:A/0003:C'分割することです。つまり、3 つのレコード (おそらく 2 つの列) に分割します。 th etokens の数字およびアルファベットのコンポーネント)。これらのレコードは索引付けできます。

次に、検索文字列をトークン化し、検索トークンを新しいテーブルに結合する選択を行うだけです。それがどれほどうまく機能するかはわかりません。それは、所有している個別のトークンの数に依存します。

于 2013-01-10T13:41:45.587 に答える
2

it checks every row and see if they have the same "group".

IMHOグループがデータ構造の基本要素である場合、データベース構造に欠陥があります。各グループを独自のセルに正規化する必要があります。説明した構造により、複合値をフィールドに格納することが明確になります。

テーブルを 3 つに分割します。

  • グループ シーケンスの「ヘッダー」情報用の 1 つ
  • グループ自体の 1 つ
  • 両者をつなぐテーブル

これらの行に沿ったもの:

CREATE TABLE GRP_SEQUENCE_HEADER (
    ID BIGINT PRIMARY KEY,
    DESCRIPTION TEXT
  );


CREATE TABLE GRP (
    ID BIGINT PRIMARY KEY,
    GROUP_TXT CHAR(6)
  );

CREATE TABLE GRP_GRP_SEQUENCE_HEADER (
    GROUP_ID BIGINT, 
    GROUP_SEQUENCE_HEADER_ID BIGINT,
    GROUP_SEQUENCE_HEADER_ORDER INT, /* For storing the order in the sequence */
    PRIMARY KEY(GROUP_ID, GROUP_SEQUENCE_HEADER_ID)
  );

(もちろん、外部キーを追加し、最も重要なのは必要なインデックスを追加することです)

次に、入力をグループに分割し、適切にインデックス付けされたテーブルに対して単純なクエリを実行するだけです。

また、重複を保存しないことで、おそらくディスク容量も節約できます...

「類似」シーケンスの ID を検索するサンプル クエリ:

SELECT ggsh.GROUP_SEQUENCE_HEADER_ID,COUNT(1)
FROM GRP_GRP_SEQUENCE_HEADER ggsh  
JOIN GRP g ON ggsh.GROUP_ID=g.GROUP_ID
WHERE g.GROUP_TXT IN (<groups to check for from the sequence>)
GROUP BY gsh.ID
HAVING COUNT(1) BETWEEN 3 AND 16 --lower and upper boundaries

これは、現在のシーケンスが類似しているすべてのヘッダー ID を返します。

編集 もう少し考え直すと、グループを 2 つの部分に分割することもできますが、私が理解しているように、常に完全なグループを処理する必要があるため、必要ではないようです。

EDIT2プロセスをさらに高速化したい場合は、バイジェクションを使用してシーケンスを数値データに変換することをお勧めします。たとえば、最初の 4 つの数値を整数として評価し、それを 4 ビット左にシフトし (16 倍しますが、より高速です)、文字の 16 進値を最後の場所に追加します。

例:

0001/A --> 1 as integer, A is 10, so 1*16+10 =26
...
0002/B --> 2 as integer, B is 11, so 2*16+11 =43
...
0343/D --> 343 as integer, D is 13, so 343*16+13 =5501
...
9999/E --> 9999 as integer, E is 14, so 9999*16+14 =159998 (max value, if I understood correctly)

数値は DB によってより効率的に処理されるため、パフォーマンスがさらに向上するはずです (もちろん、新しい構造を使用した場合)。

于 2013-01-10T13:15:53.257 に答える
0

人々がコメントしているように、データを正規化することで大きなメリットが得られますが、キーを使用して一時テーブルを作成したり、「/」の列を展開したりすることはできません。

KEY | "0001:A/0002:A/0003:A/0006:C"
KEY1| "0001:A/0002:A/0003:A"

KEY | 0001:A
KEY | 0002:A
KEY | 0003:A
KEY | 0006:C
KEY1| 0001:A
KEY1| 0002:A
KEY1| 0003:A

これにより、次のようなクエリを開発できます(テストされていません)。

SELECT
    t1.key
    , t2.key
    , COUNT(t1.*)
FROM
    temp_table t1
    , temp_table t2
    , ( SELECT t3.key, COUNT(*) AS cnt FROM temp_table t3 GROUP BY t3.key) t4
WHERE
    t1.combination IN ( 
        SELECT 
            t5.combination 
        FROM 
            temp_table t5 
        WHERE 
            t5.key = t2.key)
    AND t1.key <> t2.key
HAVING
    COUNT(t1.*) = t4.cnt

では、key1がキーの適切なサブセットである2つのキーを返しますか?

于 2013-01-10T13:42:59.027 に答える
0

特別な「インデックス」を構築することをお勧めできると思います。かなり大きくなりますが、超高速の結果が得られます。

このタスクを一連のシンボルを検索するものと考えてみましょう。設計条件があります。シンボルはパターン「NNNN:X」で作成されます。ここで、NNNN は数字 [0001-9999]、X は文字 [AE] です。したがって、アルファベットには 5 * 9999 = 49995 の記号があります。このアルファベットの単語の最大長は 16 です。

シンボルの組み合わせの単語セットごとに構築できます。たとえば、単語「abcd」には次の組み合わせがあります。

abcd
abc
ab
a
abd
acd
ac
ad
bcd
bc
b
bd
cd
с
d

シンボルは単語でソートされるため、組み合わせは 2^N-1 (4 つのシンボルで 15) しかありません。16 シンボル ワードの場合、2^16 - 1 = 65535 通りの組み合わせがあります。

そこで、このような追加の索引構成表を作成します

create table spec_ndx(combination varchar2(100), original_value varchar2(100))

パフォーマンスはオーバーヘッドの代償で優れています。最悪の場合、元のテーブルの各レコードには 65535 の「インデックス」レコードが存在します。
したがって、1 億テーブルの場合、6 兆テーブルになります。しかし、値が短い場合、「特別なインデックス」のサイズは大幅に減少します。

于 2013-01-11T09:34:58.977 に答える