SQL Data Warehouse の Azure コンカレンシーとワークロード管理 https://azure.microsoft.com/en-us/documentation/articles/sql-data-warehouse-develop-concurrency/を読ん で、スケールに基づいて使用できる同時クエリですが、私が理解できないため、ここで質問を提起するのは、ドキュメントの状態をテストするときに、Azure が主張する結果を得ることができないということです。クエリを同時に実行すると、シリアルで実行するのとほぼ同じ時間がかかります。
例 ここにテストの例を示します (単なるテストです) 5 つのストアド プロシージャがあり、個別に実行すると、完了するまでにそれぞれ約 1 秒かかります。したがって、5 つすべてを連続して実行すると約 5 秒かかりますが、これは予想どおりですが、5 つすべての sproc を同時に実行すると、1 秒強で完了すると予想されますが、完了するまでに約 4.5 ~ 4.7 秒かかります。
Azure の専門家が何が起こっているのか説明できますか?
リソースの競合ではないかと思いましたが、5 つの sproc が実行されている間、sys.dm_pdw_resource_waits はブロックを示していません。
sys.dm_pdw_exec_requests を実行すると、5 つの exec sproc クエリがすべて数ミリ秒以内に送信されていることがわかります。Start_time と End_compile_time についても同様です。5 つの sproc すべての end_time は再び数ミリ秒以内ですが、Total_elapsed_time は予想される 1000 ミリ秒ではなく 5000 ミリ秒に近づいています。sproc を単独で実行すると、所要時間は約 1000 ミリ秒になります。Concurrency は 5 つの sproc を同時に開始するかのように見えますが、内部的にはキューに入れられ、順番に実行されます。私はもともと、5 つの sproc に十分な 8 つのスロットを持つ DW200 でテストしていました。安全のために、最大 32 個の同時クエリを許可する DW1000 にスケールアウトしましたが (smallrc を使用しています)、この問題は解決しませんでした。
これをテストした方法は次のとおりです(DW1000を使用)
1000 レコードを 5 つの個別のステージ テーブル (ステージ 1、ステージ 2 など) にロードしました。
CREATE TABLE dbo.Stage1 ( ShortId bigint NOT NULL ,TestName varchar(50) NOT NULL ,TestValue varchar(50) NOT NULL ,CreateDate DateTime NOT NULL ) WITH ( DISTRIBUTION = HASH (ShortId) )
5 つのファクト テーブル (fact1、fact2 など) を作成しました。各テーブルにはステージと同じ 4 つの列があり、最初の列のハッシュを使用して分散されます。列ストア インデックスは含めませんでした (これは単なるテストであることを忘れないでください)。
CREATE TABLE dbo.Fact1 ( ShortId bigint NOT NULL ,TestName varchar(50) NOT NULL ,TestValue varchar(50) NOT NULL ,CreateDate DateTime NOT NULL ) WITH ( DISTRIBUTION = HASH (ShortId) )
ステージからファクトにデータを挿入する 5 つのストアド プロシージャを作成しました。
CREATE PROCEDURE dbo.TestLoad1 AS BEGIN INSERT INTO dbo.Fact1 --this is dbo.Fact2 in sproc 2 etc... SELECT stg.ShortId ,stg.PropertyName ,stg.PropertyValue ,stg.AcquistionTime FROM dbo.Stage1 stg WHERE stg.ShortId NOT IN (SELECT ShortId from dbo.Fact1) --Fact2 etc.. END
C# で、5 つの接続とコマンドを作成し、BeginExecuteReader/EndExecuteReader を使用して sproc を実行するクイック テスト メソッドを作成しました。(これは単なるテストなので、スタイル/コードは許してください)
SqlConnection cnn1 = new SqlConnection("Data Source=<server>;Initial Catalog=<database>;Persist Security Info = True;User ID =<username>;Password = <password>;Pooling = False;MultipleActiveResultSets = False;Connect Timeout = 30;Encrypt = True;TrustServerCertificate = False"); SqlConnection cnn2 = new SqlConnection("Data Source=<server>;Initial Catalog=<database>;Persist Security Info = True;User ID =<username>;Password = <password>;Pooling = False;MultipleActiveResultSets = False;Connect Timeout = 30;Encrypt = True;TrustServerCertificate = False"); SqlConnection cnn3 = new SqlConnection("Data Source=<server>;Initial Catalog=<database>;Persist Security Info = True;User ID =<username>;Password = <password>;Pooling = False;MultipleActiveResultSets = False;Connect Timeout = 30;Encrypt = True;TrustServerCertificate = False"); SqlConnection cnn4 = new SqlConnection("Data Source=<server>;Initial Catalog=<database>;Persist Security Info = True;User ID =<username>;Password = <password>;Pooling = False;MultipleActiveResultSets = False;Connect Timeout = 30;Encrypt = True;TrustServerCertificate = False"); SqlConnection cnn5 = new SqlConnection("Data Source=<server>;Initial Catalog=<database>;Persist Security Info = True;User ID =<username>;Password = <password>;Pooling = False;MultipleActiveResultSets = False;Connect Timeout = 30;Encrypt = True;TrustServerCertificate = False"); SqlCommand cmd1; SqlCommand cmd2; SqlCommand cmd3; SqlCommand cmd4; SqlCommand cmd5; IAsyncResult result1; IAsyncResult result2; IAsyncResult result3; IAsyncResult result4; IAsyncResult result5; SqlDataReader reader1; SqlDataReader reader2; SqlDataReader reader3; SqlDataReader reader4; SqlDataReader reader5; cnn1.Open(); cnn2.Open(); cnn3.Open(); cnn4.Open(); cnn5.Open(); cmd1 = new SqlCommand("dbo.TestLoad1", cnn1); cmd2 = new SqlCommand("dbo.TestLoad2", cnn2); cmd3 = new SqlCommand("dbo.TestLoad3", cnn3); cmd4 = new SqlCommand("dbo.TestLoad4", cnn4); cmd5 = new SqlCommand("dbo.TestLoad5", cnn5); cmd1.CommandType = CommandType.StoredProcedure; cmd2.CommandType = CommandType.StoredProcedure; cmd3.CommandType = CommandType.StoredProcedure; cmd4.CommandType = CommandType.StoredProcedure; cmd5.CommandType = CommandType.StoredProcedure; result1 = cmd1.BeginExecuteReader(CommandBehavior.SingleRow); result2 = cmd2.BeginExecuteReader(CommandBehavior.SingleRow); result3 = cmd3.BeginExecuteReader(CommandBehavior.SingleRow); result4 = cmd4.BeginExecuteReader(CommandBehavior.SingleRow); result5 = cmd5.BeginExecuteReader(CommandBehavior.SingleRow); reader1 = cmd1.EndExecuteReader(result1); //this is where the code waits for 5 seconds reader2 = cmd2.EndExecuteReader(result2); reader3 = cmd3.EndExecuteReader(result3); reader4 = cmd4.EndExecuteReader(result4); reader5 = cmd5.EndExecuteReader(result5); reader1.Close(); reader2.Close(); reader3.Close(); reader4.Close(); reader5.Close();
この C# コードをデバッグする場合、reader1 = cmd1.EndExecuteReader(result1); という行に到達するまで、各ステートメントは 1 ミリ秒未満です。ここでは、4 ~ 5 秒待機してから次に進み、その後のすべての行が再び高速になります (<1ms)。
その遅延の間に select * from sys.dm_pdw_exec_requests を実行すると、5 つの要求すべてがキューに入れられて実行されていることがわかります。クエリの再実行を続けると、クエリの実行時間が長くなり続け、突然 (約 5 秒) 5 つのクエリすべてが完了したと表示されます。
私が間違っていること、または Azure SQL DW が内部で行っていることを説明する際に、どんな助けもいただければ幸いです。
ありがとうございました