2010-12-17 2 views
6

私のテーブルには、 "id"(自動インクリメント、プライマリ)と "ナンバー"(ユニーク)の2つのカラムがあります。今度は次のようにしたいと思います:MySQL - 存在する場合、主キーを取得します。それ以外のエントリ

  • この番号がすでに存在する場合は、idを返します。
  • 他の場合は、テーブルにエントリを追加し、そのIDを返します。

このジョブを実行する最も効率的な方法は何ですか?

注:

  • 数が新しいことに大きい可能性があります。
  • テーブルには何十万ものレコードが含まれます。

ありがとうございました!

+1

私が考えることができる最善の方法は、ストアドプロシージャです。私はすぐにサンプルを提供することはできませんが、それを見てください –

答えて

6
INSERT IGNORE INTO table (number) VALUES (42); 

SELECT id FROM table WHERE number = 42; 

おそらくMySQLで最も効率的です。ストアドプロシージャを使用すると、それらを一括して処理することができます。これは、ほんの少し効率的かもしれません。

EDIT:

あなたは新しい数字が出てくることは稀になるだろうと思うなら、これはさらに高速になります。

SELECT id FROM table WHERE number = 42; 

if (!id) { 

    INSERT INTO table WHERE number = 42; 
    id = SELECT @LAST_INSERT_ID; 

} 

同時スレッドが同時にその後、選択した場合の可能な競合状態がここにあります同じ番号を同時に挿入してください。この場合、後の挿入は失敗します。このエラー状態を再選択することで、これから回復することができます。ここで

+0

私は私の質問を更新しました。テーブルには何十万ものレコードがあり、新しい番号を取得する確率は高くなります。その多くのレコードに対してストアドプロシージャを作成するとどのくらいの違いがありますか? – Saad

+0

その場合、私は選択を挿入し、よりシンプルで競合状態はないと思います。データベースサーバーがWebサーバーの近くにあると仮定すると、ストアードプロシージャーの違いはほとんどありません。両方のコードパスを記述してストレステストを行うことで、これを簡単にテストできます。 – Chris

4

はあなたが記述何がそのような保存された機能である:

CREATE FUNCTION `spNextNumber`(pNumber int) RETURNS int(11) 
BEGIN 
DECLARE returnValue int; 
SET returnValue := (SELECT Number FROM Tbl WHERE Number = pNumber LIMIT 1); 
IF returnValue IS NULL THEN 
    INSERT IGNORE INTO Tbl (Number) VALUES (pNumber); 
    SET returnValue := pNumber; -- LAST_INSERT_ID() can give you the real, surrogate key 
END IF; 
RETURN returnValue; 
END 
+0

これを使用する方法: INSERT IGNORE INTO人数(数値)VALUES(pNumber); SET returnValue:=(SELECT番号人数WHERE数値= pNumber LIMIT 1); もっと効率的だと思いますか? – Saad

+0

これは、クリスが上記のように重複の頻度に依存します....不要な挿入を試みてIGNOREを捕まえることはおそらく、選択...限界1よりもコストがかかるでしょう。しかし、レースについての彼のポイント条件この回答のインサートにIGNOREを追加しました。 – Tahbaza

+0

助けてくれてありがとうTahbaza!私は私の質問を改訂し、もう少し詳細を追加しました。あなたの解決策が依然として最高かどうかを確認してください、あるいはそれを修正したいですか? – Saad

1

私は、これは古いです知っているが、それは共通の問題です。だから、ここで解決策を探している人のために、パフォーマンスベンチマークでこのタスクを達成する4つの方法があります。 http://mikefenwick.com/blog/insert-into-database-or-return-id-of-duplicate-row-in-mysql/

+2

このリンクは質問に答えるかもしれませんが、答えの本質的な部分をここに含めて参考にしてください。リンクされたページが変更された場合、リンクのみの回答は無効になります。 –

+1

https://web.archive.org/web/20150915085727/http://mikefenwick.com:80/blog/insert-into-database-or-return-id-of-duplicate-row-in-mysql/ – dt192