2014の12月6日分の記事です。PODで出版させて頂いております。ここから---来年の1月16日(金)にPostgreSQLパフォーマンスチューニング実例セミナーを開催することになりました。ご興味のある方は是非ご応募ください。ここまで---この記事以外に全く記事がないことからもお分かり頂けるように、記事の投稿の為にわざわざブログを解説したわけですが、大した記事は書けませんのであしからず...早速、本題に入ります。テストデータはなるべく本番環境のデータに近い内容であるべきなのですが、大量のリアルなデータを作成するには、それなりにテクニックが必要となります。Calendarで笠原さんが書かれていますので未読の方はまずはそちらの記事をご覧ください。リアルなデータを作成するには色々と問題があるわけですが、その一つとしてランダム性が挙げられます。generate_series関数を使えば大量の連番データは容易に作成できますが、そこにランダム性を加えるとなると一工夫が必要となるわけです。ランダムなだけであればrandom関数でも噛ませれば済む話なのですが、「ランダム性もあって整合性も保たれてなければならない」となると更に工夫が必要となります。先日、「シーケンス列とレコード作成日時列」の2列を持つテーブルのサンプルデータを作成する機会がありました。簡略化しますが、以下のようなイメージです。:で、testtimeにランダム性を持たせたいわけですが、現実のデータを模するのであれば、testtimeは、seqが小さいレコードより大きな値でなければなりません。ランダムの間隔でレコードが作成されていくのを模したいわけです。本当にランダム性が高いといえるか疑問はありますが、以下のようにサンプルデータを作成したとします。:レコード単位に1分ずつ加算させつつ、60秒未満のランダムな秒数を減算します。仮にseqが1のレコードが最小の減算値で、逆にseqが2のレコードが最大の減算値であったとしても、1のtesttimeが2を上回ることはない......筈なのですが、確認したくなるのが人情でしょう。余談ですが、100点満点のテストの点数のサンプルデータを作成する場合、ceil(random()*100)とやりたくなりますが、これだと0点が出ないことになるので、ceil(random()*101)-1かfloor(random()*101)としないと求めたい結果が出ません。1.0の範囲の乱数値」と説明されています。この説明が正しければ、random関数でジャスト0が出力される可能性があるということになります。以下のSQLで10億回ほど施行してみましたが0は出ませんでした。precisionを返すようですが、公式ドキュメントの浮動小数点データ型の説明を簡単に読んだ限りでは、相当な桁数まで行くようですね...本当に0が出るのか確認するためにはソースを読んだ方が早そうです。testtimeがseqと同様に昇順となっているか確認する方法としてまず思いつくのは、以下のように自己結合を用いる方法でしょうか。rows)ただ、この方法ですと抜け番のない列がないと実施できません。方法は色々とあると思いますが、個人的にはWindow関数をよく使っています。row_numberを取得するために使われたことがある人も多いかと思いますが、普通の集約関数も大変便利に使えます。以下のように使えば、seqでソート後のテーブルに対して、上から順に各行時点での最大値を取得できます。:後は、testtimeとmaxの値が異なる行が存在しないかを確認するだけです。rows)因みに、今回のケースでは自己結合よりWindow関数を利用した方が約1.5倍ほど高速でした。ここで記事を終えても良いのですが、もう一つありがちな罠を紹介しておきます。1回のSQLだけで整合性のあるデータを作らなければならないわけでは必ずしもありません。データを作成後に、後から問題のあるデータを修正するというやり方もあるかと思います。深く考えずにやってしまいますと、その修正により整合性が失われてしまうことがあります。row)ご覧のように、整合性に問題のあるデータが発生してしまいました。日付を見れば原因はすぐにお分かり頂けるかと思いますが、うるう年の影響です。12:00:00となります。12:00:00このように、前後関係が逆転してしまう可能性があるわけです。「自分はこんなドジは踏まない」という方も多いかと思いますが、大量のテストデータを作成する場合は、僅かな意識漏れが結果として大きな違いを生む可能性があります。テストデータを使ってテストをする前に、そのテストデータ自身をテストすることを強くお勧め致します。12月7日は、nuko_yokohamaさんです。(カンファレンスお疲れ様でした。