質問
これはおそらく一般的な状況ですが、SOまたはGoogleで特定の答えを見つけることができませんでした。
MySQLデータベースには、非常に重要であり、重複する行がないように維持する必要がある友人関係の大きなテーブル(1,000万行)があります。テーブルには、ユーザーのUIDが保存されています。テーブルのSQLは次のとおりです。
CREATE TABLE possiblefriends(
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
user INT,
possiblefriend INT)
テーブルの仕組みは、各ユーザーには、発見されて保存する必要があるが、「可能性のある友人」を複製する必要がある約1000人ほどの「可能な友達」があることです。
問題は、プログラムの設計により、1日の間に、行エントリを複製する場合とされない場合とされない場合がある100万行以上をテーブルに追加する必要があることです。簡単な答えは、各行が複製かどうかを確認し、そうでない場合はテーブルに挿入するように思われます。しかし、この手法はおそらく、テーブルサイズが1億行、10億列以上に増加するにつれて非常に遅くなるでしょう(すぐに予想されます)。
このユニークなテーブルを維持するための最良の(つまり最速)方法は何ですか?
常に一意の値だけのテーブルが常に手元にある必要はありません。バッチジョブには1日1回必要です。この場合、可能なすべての行を挿入するだけの個別のテーブル(重複した行とすべてを含む)を作成し、1日の終わりに、最初のテーブルのすべての一意の行を計算する2番目のテーブルを作成する必要がありますか?
そうでない場合、このテーブルの長期的な最良の方法は何ですか?
(インデックスが最良の長期ソリューションである場合、どのインデックスを使用するか教えてください)
解決
一意のインデックスを追加します (user, possiblefriend)
次に、次のいずれかを使用します。
重複した行を挿入しようとするときにエラーが発生しないようにします。
また、自動インクリメントの主キーをドロップして使用できるかどうかを検討することもできます (user, possiblefriend)
主キーとして。これにより、テーブルのサイズが小さくなり、プライマリキーがインデックスとして機能し、追加のインデックスを作成する必要がないようにします。
参照:
他のヒント
一意のインデックスを使用すると、フィールドが実際に一意であることを確認できます。次のような一意のインデックスを追加できます。
CREATE TABLE possiblefriends(
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
user INT,
possiblefriend INT,
PRIMARY KEY (id),
UNIQUE INDEX DefUserID_UNIQUE (user ASC, possiblefriend ASC))
これはまた、テーブルアクセスを大幅に上げます。
マスインサートに関する他の問題はもう少し注意が必要です。以下の内蔵のキーアップデート関数を使用することができます。
INSERT INTO table (a,b,c) VALUES (1,2,3)
ON DUPLICATE KEY UPDATE c=c+1;
UPDATE table SET c=c+1 WHERE a=1;