CosmosDB

CosmosDBのスキーマー設計は、RMDBと異なる部分があります。 RMDBの感覚でスキーマー設計をすると、RUを大きく消費したり、性能がでないケースがあります。

MicrosoftのCosmosDBチームのGithubで公開されているCosmosDB-DataModeling.pptxと、アメリカで開催されたセミナーの内容をもとに書き起こし&意訳&追記したものをde:code 2019のパーソナルスポンサーの資料として公開しました。

sample-cosmosdb-fbook

SQL Azure

Microsoft Ignightで、Azure SQL Database Hyperscaleが発表されました。
ドキドキが止まらないので、早速まとめてみました。

もう間も無く、2018/10/1からPublic Previewが開始されるようです。
GAは、いつだろー?

特徴

  • Hyperscaleは、ストレージが根幹技術にあたるサービスです。
  • 最少1TB〜100TBまでのデータベースサイズを使用できます。
    • 容量だけでなくI/O性能の改善も含めたサービスです。
  • Data StoreサーバーとLogサーバーが誕生し色々すごくなっています。
    • Time to Restoreは健在
    • バックアップはストレージスナップショットで担保
    • リストアも10分程度を目指す
  • コンピューティングとストレージが分離されたモデル
    • プライマリコンピューティング、セカンダリコンピューティング両方とも柔軟に変更可能
    • セカンダリコンピューティングはプライマリコンピューティングと同じデータストレージをみる。
      • 同じ!同じです!同じなのです。
    • セカンダリコンピューティングは読み取り専用で、プライマリコンピューティングと同じエントリポイント。(接続先サーバー名が同じ
    • 接続の切り分けは、接続文字列に「Read_Only」「Read_write(既定)」を付けるかどうかの差。

vCoreモデルをベースとしているのでDTUモデルでは使用できません。
マイグレーションなどは、インスタンスサイズ変更と同等の手順で実施できるようになるようです。

仕組み

下のスライドのスクリーンショットをみてください。

ストレージが根幹のサービスだけあって、仕組みスライドもストレージがメインとなっています。
バックエンドにデータストア層があって、そこをコンピューティングが参照する。
プライマリもセカンダリも同じデータストアを見るので、データ反映タイムラグがレプリケーションよりも断然抑え込まれています。

サービス帯

ここで掲載されています。
一番大きいのは80コアモデル。

Storage Typeがまだ、LOcal SSDとなっているのはご愛嬌。

まとめ

Azure SQL Databaseが最大容量4GBで苦しんでた皆様が解放される日はもう間も無くです!
そこまで、なんとか生き延びましょう(^ ^)

SQL Azure

MSSQL Tiger Teamが投稿したBlogを基に整理した内容です。

可容性グループはSQL Server 2012で初めてリリースされました。
可容性グループセカンダリレプリカの各データベースではトランザクションログのredoは一つのredoスレッドで制御していました。
このredoモデルは、serial redoと呼ばれていました。

SQL Server 2016で、redoモデルが強化され、redo操作を分けるためにデータベース毎に複数の並列redoワーカースレッドになりました。さらに各データベースは、ダーティページディスクフラッシュIOを管理する新しいヘルパーワーカースレッドがあります。
この新しいredoモデルは、parallel redoと呼ばれます。

新しいparallel redoは、SQL Server 2016から既定の設定で、小さいトランザクションが並列に大量に実行されるケースではredo性能の改善ができました。データの暗号化、データ圧縮の有功などのCPU負荷の高いトランザクションredo操作は、serial redoと比較してparallel redoの方が高いスループット(Redone Bytes/sec)が得られます。
さらに、間接的チェックポイントがparallel redoがヘルパーワーカースレッドにディスクIOや遅いディク用のIO waitを委任し、メインのredoスレッドがセカンダリレプリカでログレコードをより受信できるようにします。redo性能を向上させます。

しかし、parallel redoはマルチスレッドモデルでコストが高いです。

  • メインredoスレッドは、各トランザクションログredo操作の実行を停止しますが、各トランザクションログを列挙し、parallel redoワーカースレッドにディスパッチすることを担当します。テーブル(行数の小さい)の狭い範囲の行へのDMLトランザクションのredoのようなCPU負荷がかからないログredo操作のケースでは、それらのログをディスパッチするコストは非常に重いです。
  • 新しいレコードを挿入するためにページを分割するシステムトランザクションは、parallel redoワーカースレッド間でPARALLEL_REDO_TRAN_TURN waitを利用します。頻繁にinsert操作をする場合、かなりparallel redo性能を遅くします
  • 読み取りセカンダリレプリカでread-onlyクエリを実行すると、クエリスレッドはログredo操作を一時停止しようとし、DIRTY_PAGE_TABLE_LOCKでredoワーカースレッドと連携する必要があります。redoとクエリ性能が両方遅くなります。

性能研究に基づくと、次のトランザクションワークロードまたはSQL設定が既定のparallel redo モデルより良い結果となります。

  • 多くの並列の小さいトランザクション
  • 間接的なチェックポイントを伴う負荷のかかるログredo操作(データ暗号化またはデータ圧縮)
  • 読み取りをしないセカンダリレプリカ、またはたまにread-onlyクエリを読み取りセカンダリレプリカで実行する場合

次の場合は、serial redoに切り替えた方がredoスループットがよくなります。

  • 一般的なInsertや同時実効性が限られている長い時間実行するトランザクション:典型的な例は、大きなテーブルのクラスター化インデックスのオンラインIndex再構築
    • parallel redoモデルでの兆候
      • PARALLEL_REDO_TRAN_TURN waitがinsert処理量に比例して生成されます。多くのInsertが多くのpage splitを起こし、PARALLEL_REDO_TRAN_TURN waitを呼びます。
      • 性能カウンターで監視できます。(SQLServer:General Statistics、User Connections)または、プライマリレプリカのDMV(sys.dm_exec_connection、sys.dm_exec_sessions)
  • 頻繁で、長時間のread-onlyクエリをセカンダリレプリカのデータベースに実行する必要がある場合
    • parallel redoでの兆候
      • 頻繁なDIRTY_PAGE_TABLE_LOCK wait
      • 性能カウンターで監視できます(SQLServer:Database Replica、Redone Bytes/sec)クエリを実行している時としてない時でredoスループットを比較します。
  • 小さなデータセットのデータページにセカンダリレプリカでread-onlyクエリが高頻度でスキャンし、プライマリレプリカで頻繁に同じデータセットに変更を加える。クエリとredoスレッド両方に劇的な性能劣化を与えます
    • parallel redoでの兆候
      • 大量のDPT_ENTRY_LOCK wait
      • 最悪のケースでは、Latch timeoutによりSQL ErrorログにTimeout occurred while waiting for latchと記録されます。

新しいWaitの種類

いくつか紹介されていますが、個人的に興味があるものをピックアップ。

  • DPT_ENTRY_LOCK
    • ユーザークエリスレッドから追いつくためのREDOがあるdirty page entryへのアクセスを制御するロックがある時に発生します。
    • parallel redoワーカースレッドとユーザークエリが同時に同じdirty page entryにredo処理をした時のみ発生します。

補足

SQL Serverの事例として紹介されていますが、Azure SQL Database のgeo replicationを使用してセカンダリデータベースを使用しているケースでも同様の問題が発生します。
P15を使っていると、ジオレプリケーションはparallel redoが採用されているので、ここで紹介されたことと同じ問題が発生するのです。

Windows Azure

Application GatewayでLet’s Encrypt証明書を設定しようとして、はまりにはまったので対応方法をメモしておく。

今回は、Application GatewayにカスタムドメインのサブドメインをAzure DNSで割り当てて、DNS-01認証でLet’s Encrypt証明書を取得する。取得には、win-acmeを使用した。

Application GatewayのURL:yyy.xxx.example.com
Azure DNSのDNSゾーン:xxx.example.com
発行したい証明書: yyy.xxx.example.com

  1. Application Gatewayを立てる
    とりあえず自己証明書などでたててしまう。DNS-01認証なのでアクセスできる必要はないと思うけど、まぁHTTPSでたててしまう。
  2. 今回はAzure DNSを使用して、DNS-01認証をするので、カスタムドメインの向き先をAzure DNSにする。
    ちなみに今回は、xxx.example.comをAzure DNSに向けた。
    当然、Azure DNSのDNSゾーン登録はxxx.example.comになる。
    CNAMEで、「yyy」をApplication GatewayのURLに向ける。
  3. Azure DNS validationのドキュメントに従って、作業をする。
    3-1. LetsEncryptというサービスプリンシパルを作成する。
    サービスプリンシパルは、Azure Active Directoryの「アプリの登録」に登録される。表示されない場合は、「すべてのアプリケーションの表示」ボタンが表示されれたらクリック、ない場合はドロップダウンなどでフィルタリング条件を変更するといい。

    3-2. Azure DNSでDNS ゾーン(xxx.example.com)に作成したLetsEncryptサービスプリンシパルのアクセス権を付与する。
    アクセス制御画面で、「DNSゾーンの共同作成者」ロールで、LetsEncryptを登録する。

  4. win-acmeをダウンロードする。なお、サブドメインに対して、証明書を発行したい場合、特にAzure DNSに登録しているDNSゾーンが「example.com」ではなく、「xxx.example.com」のようにサブドメインの場合は、win-acmeの問題でDNS-01認証が正常に完了しない。完了させるためにはコードを修正する必要があるので、ソースコードをダウンロードする。
    Visual Studioで開いて下記部分を修正して、ビルドして実行する。

修正前

        _dnsClient.RecordSets.CreateOrUpdate(_azureDnsOptions.ResourceGroupName, 
            url.RegistrableDomain,
            url.SubDomain,
            RecordType.TXT, 
            recordSetParams);

修正後

        _dnsClient.RecordSets.CreateOrUpdate(_azureDnsOptions.ResourceGroupName, 
            "xxx.example.com",//url.RegistrableDomain,
            "_acme-challenge.yyy".//url.SubDomain,
            RecordType.TXT, 
            recordSetParams);

5. ビルドしたletencrypt.exeを起動する。
M: create new certificate with advanced optionsを選択
1: Manually input host names を選択
yyy.xxx.example.com を入力
1: [dns-01] Azure DNS を選択
Tenant Idを入力する。(Get-AzureRmSubscriptions)
Client Idを入力する。(Get-AzureRmADServicePrincipal|where DisplayName -EQ LetsEncrypt のApplication Id)
SecretはService Principalを作成するときに設定したパスワード
DNS Subscription IDは、xxx.example.comのDNSゾーンで表示されるもの
DNS Resource Groupは、xxx.example.comのDNSゾーンで表示されるもの

これで無事に証明書が発行される。

エラー

次のエラーが出るときは、「xxx.example.com」へのアクセス権を付与していることと、ソースコードを修正していることを確認してください。ソースコードを修正していないと、「example.com」DNSゾーンにレコードを作ろうとするので下記エラーが発生します。

The client ‘d38f55be-xxxx-xxxx-xxxx-xxxxx’ with object id ‘d38f55be-xxxx-xxxx-xxxx-xxxxx’ does not have authorization to perform action ‘Microsoft.Network/dnszones/TXT/delete’ over scope

SQL Azure

Azure SQL Databaseの監査ログを見るとき、知らないと面食らうというか上手く使えなくてしょんぼりすることがあります。
ちょっとしたポイントを知っておくと幸せになれます。

監査ログをAzure ポータルで参照しようと思うと最終的にはクエリエディターを起動することになります。クエリエディターのログインに使用するアカウントは管理アカウントになります。

クエリエディタが起動すると次のようなクエリが書かれています。

SELECT TOP 100 event_time, server_instance_name, database_name, server_principal_name, client_ip, statement, succeeded, action_id, class_type, additional_information
FROM sys.fn_get_audit_file(‘https://xxxxxxx.blob.core.windows.net/sqldbauditlogs/xxxxxxxxx/xxxxxxxx/SqlDbAuditing_Audit/2018-08-29/04_00_49_057_2108.xel’, default, default)
WHERE (event_time <= ‘2018-08-29T04:00:51.022Z’)
/* additional WHERE clause conditions/filters can be added here */
ORDER BY event_time DESC

Blobファイルを読み込んで検索していますね。
ファイルが細かく分かれているので、ほかのファイルも対象にしたくなります。

ドキュメント読んでワイルドカードとか試したのですが、あまりちゃんと動かず、結局たどり着いた結論は、「前方一致」したものが対象になるでした。

例えば、Blobファイルの指定を、「
https://xxxxxxx.blob.core.windows.net/sqldbauditlogs/xxxxxxxxx/xxxxxxxx/SqlDbAuditing_Audit/2018-08-29/ 」とすると、8/29のものがすべて。「
https://xxxxxxx.blob.core.windows.net/sqldbauditlogs/xxxxxxxxx/xxxxxxxx/SqlDbAuditing_Audit/2018-08-2」とすると、20日~29日が対象となります。(たぶんねw

データ量が多いと検索にえげつない時間かかります。
自分が試した環境だと10分程度でも結果出るのに1分とかかかりました。

つらいですね。
もう少し素敵な検索方法は、SQL Server Management Studioを使うことです。
ポータルでやるのはあきらめて、ここの真ん中あたりに記載がある「SQL Server Management Studio (SSMS 17 以降) で [監査ファイルの統合] を使用します。」の手順にのっとるのがいい。

これを実行すると、Blobストレージのアクセス権APIキーを設定した後、取り込みたい範囲を指定して、ローカルにダウンロードし、SSMSでフィルタリングとかをして調査をします。
めっちゃいい!と言い切れない部分もあるのですが、Azure Portalよりは断然ましです。