良い一日
開発者は、多くの場合、大量のデータに対してデータベーステストを実施するタスクを持っていますが、このまさにデータをどこで取得するのでしょうか? 結局のところ、データベースの構造が50を超えるテーブルに到達する可能性があることは誰もが知っているので、実際には手で記入する必要はありません。 また、値が他のテーブルに関連付けられている外部キーと複合主キーについて考えると、冷却をオフにすると、古いAMDに比例してヘッドが加熱し始めます。
インターネットでは、.NET、C ++、Javaなどを使用してデータベースにランダムな値を入力するための多くのソリューションがあります。 この記事では、MS SQL Serverの制御下でT-SQLツールを使用してデータベースにランダムな値を入力するトピックについて説明します。
はじめに
数日前、MS SQL Serverを実行しているデータベースにランダムデータを入力するタスクがありました。 さらに、実装全体はT-SQLによってのみ実行する必要があります。 リソースに関するこのようなソリューションを長時間検索した後、私は自分でやらなければならず、仕事に取りかかる必要があるという結論に達しました。
(最近まで) T-SQLの専門家ではなく、大学の「データベース」コースの知識しか持っていなかったため、実装は非常に「松葉杖」で遅く(主な問題)、動作していました。
この記事の主な目的は、ソリューションを最適化する可能性、または既製の実装へのリンクを含むCtrl + AとShift + DelをHabrコミュニティと議論することです。
そして、入り口にあったもの:
- 多数の関連テーブルを持つデータベース。
- すべての主キー(以降PK)は自動インクリメントです。
- 外部キー(以下FK)で構成される複合PKを含むテーブルがあります。
あなたはこれらすべてに関係していました:
- 属性(列)のタイプに応じてランダムデータを生成します。
- 自動インクリメント充填をスキップします。
- FK子テーブルをランダムなPK親テーブルで埋めます。
実装
実装全体が、他の各プロシージャを呼び出すように見えました。
- randomString-指定された長さの文字のランダムな文字列の生成。
- randomInt-指定された範囲からの乱数の生成。
- generateDataByType-テーブルの属性(列)のタイプを取得し、ランダムな値を生成するための目的のプロシージャを呼び出します。
- insertRandomData-メインプロシージャ。テーブル名と追加するレコードの数のみを入力するよう要求します。
各手順について詳しく説明することを提案します。 (読者と
は、著者とは
異なり、 SQLの基本に精通していることを前提としています)
randomStringCREATE PROCEDURE [dbo].[randomString] @inputSize int, @outputRandomString nvarchar(max) output AS BEGIN
MS SQLフォーラムで出会った最初の実装オプションの1つを使用しました。 このプロシージャは、入力として文字列の長さを受け取り、目的のサイズのタイプNVARCHAR(MAX)のランダム文字の文字列を出力します。 この場合、大量のデータに対する深刻な時間コストがないため、実装は重要ではありません。 さらに進んでいます。
randomInt CREATE PROCEDURE [dbo].[randomInt] @inputSize int, @outputInteger int output AS BEGIN DECLARE @TEMP bigint SET @TEMP = SUBSTRING('999999999999999999',1,@inputSize) SET @outputInteger = (ABS(CHECKSUM(NewId())) % @TEMP) END
機能は小さく、あまり美しくありません(特にSUBSTRINGがある場所)が、その速度には私に合っていたので、今のところはそのままにして先に進みます。
generateDataByType CREATE PROCEDURE [dbo].[generateDataByType] @tableName nvarchar(40),
したがって、「メイン」手順に到達する前に、見つかった親テーブルのデータをテーブルの外部キーに入力する際に
膨大な時間コストがかかります。 与えられた範囲の乱数を置き換えることでこの検索に気付くと、パフォーマンスが大幅に向上します。 おそらく、問題はシステムテーブルとランダムソートからのSELECT'eにあります。 比較のため:FKなしで100万行をテーブルに書き込むには約20分かかり、FKありで100万行をテーブルに書き込むには17時間以上かかります。
参考までに、1つのフィールドにクリーンなINSERTを使用して100万行を書き込むには6〜10秒かかります。現時点では、この記事を書くきっかけになった最適なものを見つけることはできませんでしたが、それについては結論を出しました。
insertRandomData CREATE PROCEDURE [dbo].[insertRandomData] @childTableName nvarchar(MAX), @insertRowCount int AS BEGIN DECLARE @i int = 0 DECLARE @columnName NVARCHAR(30); DECLARE @columnType NVARCHAR(10); DECLARE @columnLenght INT; DECLARE @columnUniq INT; DECLARE @insertQuery NVARCHAR(MAX); DECLARE @insertColumnsQuery NVARCHAR(MAX); DECLARE @insertValuesQuery VARCHAR(MAX); DECLARE @params NVARCHAR(MAX); SET @insertColumnsQuery = ''; SET @insertValuesQuery = ''; begin transaction WHILE (@i < @insertRowCount) BEGIN DECLARE columnsCursor CURSOR FOR
この手順は「比較的」時間がかかりますが、システムテーブルに忍び込んで入力に来たテーブルの構造を取得しますが、いくつかの明らかな弱点があります。 たとえば、テーブルの最初の要素をPKであると期待してジャンプします。
おわりに
上記は、そのような解決策を見つけることができなかったので、作者が心から望んでいる誰かにとって有用です。 しかし、裁判所にコミュニティに提出された決定は、時間の面で最適ではなく、重大な変更が必要です。 興味のある人が皆、私にそれを思い起こさせる(それが理にかなっているなら)か、別の道筋を示すのを助けることを願っています。