高速なデータベーススクリプトおよび展開システムの作成方法

パート1、歴史



今、歴史家は提示しようとしている

1500年後

何かがありました。

はい、何もありませんでした!

V.S.チェルノミルディン





だから、2006年に私がIT会社に入社したとき、すべては始まりました。IT会社は電気通信の分野でソリューションの開発に従事していました。 私たちのチームは、MS Sql Serverデータベースからいくつかのデータを受け取り、それを処理して折り返したC#アプリケーションを開発しました。 最初は、データベースに約10個のテーブルといくつかのストアドプロシージャがありました。 時間が経つにつれて、テーブルやその他のオブジェクトの数が増え始めました。 これらの施設の管理方法について考え始めました。 スクリプトをバージョン管理システムに保存しました。



最初はVisual StudioのDBプロジェクトを使用しましたが、時間が経つにつれて、この環境の展開に非常に長い時間がかかることが明らかになりました。 ターゲットデータベースとソーススクリプトを比較します。 さらに、データベースには、統合したがリポジトリに保存したくない大規模サブシステムのオブジェクトの一部が必要でした。 その結果、デプロイするオブジェクトのリストを含むxmlファイルを取得する簡単なアプリケーションを作成しました。 このファイルは各開発者によって手動で編集され、その「テキストの性質」により、コミット中の競合を解決できました。 将来的には、スクリプトの厳密な保存順序とロールの順序を支持して、xmlファイルを放棄しました。 (ビューの前にロールアップされたテーブルなど)



新しい問題が発生するまで、すべてが正常でした。 テクニカルサポートは、リリースブランチのコードを編集したり、クライアントで直接変更を加えたりすることがあり、次のリリースのインストール時に問題が発生することがありました。 クライアントで「違法な」変更を検出するサブシステムを実装することにしました。 アプリケーションはデータベースのスクリプトを作成し、サーバーにスクリプトを送信し、正しい構造に展開してから、展開システムに接続し、出力からリポジトリとクライアントから2つのデータベースを受け取りました。 次に、同じVisual Studioが起動され、データベースを比較しました。



スクリプトは、 SMOライブラリ(サーバー管理オブジェクト)を使用して行われました。



作業は簡単でしたが、1つの大きな問題がありました-速度。 彼女は1秒あたり約6個のオブジェクトをスクリプト化できました。 クライアント上のデータベースは合計で約10,000個のオブジェクトであり、スクリプト作成プロセスには30分かかりました。



数ヶ月前、同僚と私は、すでに行ったことのすべての長所と短所を考慮に入れて、スクリプティングとデータベース展開の最速システムを実装することにしました。 それが私たちが得たものです。



パート2、技術



現代の技術はそうです

女性の仕事を促進した

男性に現れたもの

たくさんの自由時間。

ヴラディスラフ・ジェシュチク





スクリプティング



スクリプトシステムについては、次の要件を確認しました。

•2008年以降のMs Sql Serverのすべてのバージョンのサポート。

•スクリプトは並行して作成する必要があります(データベースのスクリプト作成は数分ではなく数秒続く必要があります)。

•スクリプトストレージの構造は、設定で定義する必要があります。

•スクリプトを作成する必要があるオブジェクトの種類を選択する機能(たとえば、ストアドプロシージャのみのスクリプトを取得する)。

•ファイルシステム、アーカイブ、クラウドサービスへのスクリプトの保存。



まず、SMOを介して並行してスクリプトを実行しようとしましたが、1秒あたり約60個のオブジェクトを取得しましたが、これは良くありませんでした。 スクリプトを作成できるMs Sql Serverシステムオブジェクトのメタ情報を使用することが決定されました。 私たちは考え始め、抽象的なデータを使用してスクリプトを作成する方法を学びました。 そしてここで、JavaからのEl式が助けになりました。 短いコーディングの後、独自のテンプレートエンジンを取得しました。

主キースクリプトを生成するためのテンプレートの例:



${templ::if_cont_coll(${PKFields},${ALTER TABLE [${Schema}].[${TableName}] ADD ${templ::if_cont_field_val(${PKName},${ CONSTRAINT [${PKName}] },${})}${ConstraintType} ${PKType} ( ${templ::for(${PKFields}, ${[${FieldName}] ${Order}},${, })} )WITH (${PKProperties})${templ::if_cont_field_val(${PKFileGroup},${ ON [${PKFileGroup}]},${})}${templ::if_cont_coll(${PartitionPKFields},${(${templ::for(${PartitionPKFields},${[${PartitionFieldName}]},${,})})})}})}
      
      





この論理構造のテンプレートは、 MSDNの説明に似ています



データベースオブジェクトに関するメタ情報を読み込むとき、一連のフィールドとコレクションを形成します。 特定の主キーに対して、Schema、TableNameなどのフィールドを取得します。 キーの構築に使用されるフィールドは、PKFieldsコレクションにロードされます。



テンプレートエンジンを使用すると、任意の機能を実装できます。 たとえば、条件文IF ... ELSE、FOR文などを編成できます。 (例では、すべての関数はキーワードtempl::)で始まります。



これで、各タイプのオブジェクトのテンプレートができました。今度は、スクリプトが遅いという問題を解決します。

特定の種類のスクリプトに関する情報を含む特別なTypeMapperファイルを作成しました。 このファイルからの抜粋:



 <TypeGroup name="MSSQL2008" version="Microsoft SQL Server 2008"> <Types> <Type name="Users" pattern ="${RootPath}\Users\${Name}.sql" priority="0" sqltype="SQL_USER" TopLevel="true"> <Factory assembly="ScriptEngine" typename="ScriptEngine.Templates.UserDescriptorFactory"></Factory> <ScriptOption assembly="ScriptEngine" typename="ScriptEngine.Templates.UserScriptOption"></ScriptOption> <TemplateGenerator assembly="ScriptEngine" typename="ScriptEngine.Templates.UserTemplateGenerator"></TemplateGenerator> </Type>
      
      





この構造により、Ms Sql Serverのバージョンに応じて異なるルールを定義し、スクリプトが保存されるパスのマスク(同じテンプレートエンジン)を指定し、メタ情報の読み込みとスクリプトテンプレートの作成を担当する型名を決定できます。



その結果、次の処理パイプラインをスクリプト化して構築する型のリストを取得します。



画像



その結果、Ms Sql ServerでN個のクエリを作成し、それらを使用して特定のオブジェクトを記述する記述子オブジェクトを作成し、競合するキューを介してTemplateGeneratorに渡します。 テンプレートジェネレーターは、論理コアの数だけ並行して動作し、完成したスクリプトとその名前を別の競合するキューを介してFileSaverに渡します。 FileSaverは、ディスクサブシステムの帯域幅に応じて、ファイルを並行して保存します。



その結果、15,000個のオブジェクトを含むデータベースは、ローカルのMs Sql Serverインスタンスを持つ通常のデスクトップコンピューターで50秒でスクリプト化されますが、SMOは50分でこれを実行できます。



また、スクリプト作成時に特別な依存関係グラフを作成します。これについては、次のパートで詳しく説明します。



展開



記事の最初の部分で、冒頭で、開発者が作成したフラットリストからスクリプトを展開したことを説明しました。 不便だと判断し、この問題を解決しようとしました。 スクリプトを作成するとき、特別な依存関係グラフを作成します。このグラフには、特定のスクリプトを順番に展開する必要があるという情報が含まれています。 したがって、同じレベルにあるスクリプトを並行して実行できます。

依存関係グラフがあり、スクリプトディレクトリに新しいスクリプトが追加された場合はどうなるでしょうか。

この場合、スクリプトが依存関係グラフで見つからない場合、スクリプトは独立していると見なされ、最初のバッチで実行されます。 「クラッシュ」する場合、そのようなスクリプトは「セカンドチャンス」キューに配置されます。 すべてのスクリプトが展開された後、セカンドチャンスキューからの再展開が発生します。 これは、「セカンドチャンス」の新しい行が空になるまで繰り返されます。



パート3、実用的



理論的には、何でも起こり得る

何でも。 しかし、実際には

多くの場合、好ましくないことがすべて起こります。

ユーリ・タターキン





なんとか取得できました。 データベースオブジェクトのスクリプトをすばやく取得する方法を学びました。 依存関係を指定してスクリプトを実行します。 これらの機会から得たもの。



Spindle Scripting Too lは、スクリプトを作成するオブジェクトの種類を選択することで、数回クリックするだけでデータベーススクリプトを取得できるデスクトップアプリケーションです。 スクリプトファイル名を生成するためのパターンを変更できます。 スクリプトは、ディスク、アーカイブ、クラウドサービスに保存できます。 これに加えて、依存関係グラフとプロジェクトファイルが形成されるため、目的のプロジェクトファイルを選択するだけで展開を実行できます。



スピンドルSSMSアドイン-SQL Server Management Studioのアドオン。 このアドオンを使用すると、オブジェクトエクスプローラーウィンドウでデータベースを選択してデータベーススクリプトを作成できます。 また、独自の機能-スクリプトエディターウィンドウで、データベースオブジェクトを選択し、マウスの右ボタンを押して、コンテキストメニューでスクリプトを受信するコマンドを選択します。 スクリプトは数ミリ秒で形成され、新しいエディターウィンドウで開きます。 この機能は、ビルトイン機能とは異なり、リモートサーバーでうまく機能します。



さて、甘い人のために-2つのデータベースを数秒で比較できることに気付きました。



Spindle Comparerは、超高速のデータベースコンパレータです。 2つのデータベースを選択して、[比較]ボタンをクリックするだけです。



All Articles