テーブルのIDを採番する際、通常はAUTO_INCREMENTを使うと思いますが、
レコード数・増数が多く、DBのShardingが求められる場合、AUTO_INCREMENTは使えません。
そのため、IDを払い出す採番用のテーブルを用意し、レコード追加時のIDを管理します。
まず準備としてテーブルを作成し、IDを数え上げるためのレコードを1行だけ追加します。
この採番用テーブルをDBIから利用する場合は下記のようなコードになります。
最近のアプリケーションだと上のようにDBIで生のクエリを扱うことはまれで、
DBIx::ClassなどのORMを使うことが多いでしょう。
DBIx::Class利用して先ほどと同じことをする場合は以下のようになります。
個人的に詰まったのは
ここの肝は下記の部分です。
レコード数・増数が多く、DBのShardingが求められる場合、AUTO_INCREMENTは使えません。
そのため、IDを払い出す採番用のテーブルを用意し、レコード追加時のIDを管理します。
まず準備としてテーブルを作成し、IDを数え上げるためのレコードを1行だけ追加します。
# テーブルの作成 CREATE TABLE `id_pot` ( `id` bigint(10) unsigned NOT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8; # IDを数え上げるためのレコードを1行だけ追加 INSERT INTO id_pot SET id = 0;
この採番用テーブルをDBIから利用する場合は下記のようなコードになります。
my $dbh = DBI->connect( 'dbi:mysql:database', 'user', '', ); my $sth = $dbh->prepare( 'UPDATE id_pot SET id = LAST_INSERT_ID(id + 1)' ); $sth->execute(); print $sth->{mysql_insertid}; ## 1が出力される
最近のアプリケーションだと上のようにDBIで生のクエリを扱うことはまれで、
DBIx::ClassなどのORMを使うことが多いでしょう。
DBIx::Class利用して先ほどと同じことをする場合は以下のようになります。
use strict; use warnings; use DBIx::Class::Schema::Loader; my $schema = DBIx::Class::Schema::Loader->connect( 'dbi:mysql:database', 'user', '', ); my $resultset = $schema->resultset('IdPot'); $resultset->search->update({ id => \'LAST_INSERT_ID(id + 1)', }); print $schema->storage->last_insert_id; ## 1が出力される
個人的に詰まったのは
- SET id = id + 1 のインクリメントを行うSQL文のDBIx::Classでの実行
- LASET_INSERT_IDの取得
ここの肝は下記の部分です。
$resultset->search->update({ id => \'LAST_INSERT_ID(id + 1)', }); $schema->storage->last_insert_id;