MySQL で大量の連番を生成したい
MySQL を使ったアプリケーションの性能試験用に大量のデータを生成したかったのですが、
PostgreSQL の generate_series みたいなものが無いので、SQL だけでデータを insert ~ select できない・・・
ググってみる
ユーザ変数を使って生成する方法を多くの方が挙げていました。
こんなの。
generate_series.sql
select
@seq := @seq + 1 as value
from
-- ここのテーブルは何でも良いが、欲しい連番の最大数と同じだけのレコードが入ってないとダメ
information_schema.tables
, (select @seq := 0) x
;
この方法の問題点は、欲しい最大数と同じだけのレコードが格納されているテーブルが必要なところです。
上の例では、 information_schema.tables
に 100 件しかレコードが無ければ、連番は 100 止まりになってしまいます。
直積で組んでみる
今回は 10,000,000 までの連番が欲しかったのですが、そんな件数のレコードが予め入っているテーブルは用意できなかったので、以下のように愚直な計算で連番を生成しました。
generate_series_with_cross_join.sql
insert into test_data
with part (value) as (
select 0
union all select 1
union all select 2
union all select 3
union all select 4
union all select 5
union all select 6
union all select 7
union all select 8
union all select 9
)
, seq (value) as (
select
(g.value * 1000000) +
(f.value * 100000) +
(e.value * 10000) +
(d.value * 1000) +
(c.value * 100) +
(b.value * 10) +
a.value value
from
part a
, part b
, part c
, part d
, part e
, part f
, part g
order by
1
)
select
-- ここで連番を使って何かする
s.value
from
seq s
;
cross join するテーブルを増やせば桁は増やせますが、流石にこの桁数になってくるとちょっと反応が悪い。
(手元のマシンではクエリの応答が返ってくるまでに約 8 秒かかりました)
とはいえ、火種(?)になるテーブルが一切無くても好きなだけ連番を生成できるので、ヨシとします。
まとめ
直積を使って連番を生成する方法を紹介しました。
当初は load data local infile ...
で CSV を投入しようとしていたのですが、そもそも CSV を試験用サーバにアップロードする段階で途方も無い時間がかかっていたので、かなり時間短縮になりました。