2016-03-29 7 views
4

アイテムを格納するデータベースにテーブルがあります。各項目には一意のIDがあり、挿入時にDBが生成します(自動インクリメント)。
ユーザーは、データベースにX項目を追加する特定のタスクを実行できますが、プログラム(MySQLコネクタを使用するC++サーバーアプリケーション)は、データベースが直ちに生成したIDを返す必要があります。たとえば、6つのアイテムを追加する場合、サーバーは6つの新しい一意のIDをクライアントに返す必要があります。
このようなことを行う最も早く/最もクリーンな方法は何ですか?これまでのところ、私はINSERTの後にSELECT、その後はINSERTとなり、その後にはlast_insert_idとなりましたが、追加するアイテムが50個ある場合は、少なくとも数秒でユーザーエクスペリエンスが悪くなります。いくつかの挿入行を選択する最速の方法

sql_task.query("INSERT INTO `ItemDB` (`ItemName`, `Type`, `Time`) VALUES ('%s', '%d', '%d')", strName.c_str(), uiType, uiTime); 

IDの取得:

uint64_t item_id { sql_task.last_id() }; //This calls mysql_insert_id 
+0

いくつかのコードを追加してください。 –

+0

申し訳ありませんが、私はいくつかのコードを追加しました。それはすべて正常に動作しますが、それは全く速くはありません。 – Spook

答えて

-1

IDがautoincrementalであるあなたと、あなたは2つだけSELECTクエリを行うことができます - INSERTクエリの前と後:

SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name = 'dbTable' AND table_schema = DATABASE(); 
-- 
-- INSERT INTO dbTable... (one or many, does not matter); 
-- 
SELECT LAST_INSERT_ID() AS lastID; 

これはあなたを与えるだろう挿入された最初と最後のIDの間のsiquence。次に、それらの数を簡単に計算できます。

+0

それは簡単ではありません。並行セッションでも挿入IDを増やすことができます。もちろん、MySQLのマルチマスタークラスターは1ずつインクリメントされません。 – rkosegi

+0

rkosegiにも同意しますので、私はそれに同意します。同じテーブルにアイテムを追加できる外部ツールがあり、同時にアイテムを追加すると、クライアントは異なるIDを取得することがあります。 – Spook

+0

一般的に@rkosegiはい、あなたは正しいですが、それは依存しています。 InnoDBは挿入中にロックを実行するので、他のインサートはトランザクションが完了するのを待たなければなりません(もしあれば)。すべては実装によって異なります。 – mitkosoft

1

私はあなたのデザインを若干再考する必要があると信じています。受注のアナロジーを使ってみましょう。受注(または請求書番号)を使用すると、請求書番号(auto_incr)と複数の明細番号(auto_inc)が取得されます。

(GUIから)挿入するために受注とすべての明細が選択され、挿入が実行されます。まず、受注行が挿入され、そのIDが変数に保存され、それ以降のコールでは明細が挿入されます。ただし、auto_inc id値がすぐに返されることなく、広告申込情報が挿入されます。アプリケーションでは、最後に受注番号が返されます。あなたのアプリが後続の通話でこの販売注文番号をどのように使用するかはあなた次第です。しかし、すべてのXまたは50行を一度に取り出すことは即座に行う必要はありません。販売注文番号が凍結され、どこかに保存されるからです。その注文番号XYZと呼ぶことにしましょう。

あなたが実際に情報が必要な場合には、例えばコールはあなたがマルチユーザシステムにおける番号の連続ブロックを受信する保証がないことをことを覚えておく必要があり

select lineItemId 
from lineItems 
where salesOrderNumber=XYZ 
order by lineItemId 

ようになります。 。正しい販売注文番号で適切に結びついているので、あなたにとって重要ではありません。ここでもまた、上記は単なる例示に過ぎず、例示目的で使用されている。

+0

その類推は素晴らしかった、ありがとう!実際には、サーバーの動作を再現しようとしているので、私の設計ではありませんが、その部分は混乱しています。ユーザーはカップルアイテムを一度に購入することができ、サーバーはそれらをDBに追加して、購入したアイテムごとに固有のIDをクライアントに返します。彼らはそれをとても速くするので、私が逃したものがあるかどうか疑問に思っていました。 – Spook

0

これは一般的ですが問題を解決するのは難しいです。 mysqlについてはわかりませんが、PostreSQLはシーケンスを使用して自動IDを生成します。フレームワーク(オブジェクト関連のマッパー)を挿入すると、多くの値を挿入すると予想されるときに使用されます。一連のIDのシーケンスを直接照会し、既知のIDを使用して新しい行を挿入します。そうすれば、各挿入後にIDを取得するための追加クエリは必要ありません。

異なるライターが挿入を混在させるとき、関係ID - 挿入時間は単調でないことが欠点です。これはデータベースにとっては問題ではありませんが、プログラムの中にはあまり書かれていないものもあります。