我已阅读 SQL 数据仓库中的 Azure 并发和工作负载管理 https://azure.microsoft.com/en-us/documentation/articles/sql-data-warehouse-develop-concurrency/ 并了解对数量的限制可以根据规模使用的并发查询,但我无法理解并因此在这里提出的问题是,在测试文档状态时,我无法得到 Azure 声称的结果是真的。并发运行查询所花费的时间几乎与串行运行它们一样长。
示例 这是一个测试示例(只是一个测试) 我有 5 个存储过程,当它们单独运行时,它们每个大约需要 1 秒才能完成。因此,当我连续运行所有 5 个存储过程时,它们大约需要 5 秒,这是可以预料的,但是当我同时运行所有 5 个存储过程时,我希望它们在 1 秒多一点的时间内完成,但它们大约需要 4.5-4.7 秒才能完成。
一些 Azure 专家可以解释可能发生的情况吗?
我认为这可能是资源争用,但 sys.dm_pdw_resource_waits 在 5 个存储过程运行时显示没有阻塞。
当我运行 sys.dm_pdw_exec_requests 时,我看到所有 5 个 exec sproc 查询都在几毫秒内提交。Start_time 和 End_compile_time 也是如此。所有 5 个 sproc 的 end_time 再次在几毫秒内,但 Total_elapsed_time 接近 5000 毫秒,而不是预期的 1000 毫秒。如果我自己运行任何 sproc,则持续时间约为 1000 毫秒。就好像并发将同时启动所有 5 个存储过程,但在内部它们排队并按顺序运行。我最初是在一个有 8 个插槽的 DW200 上测试的,这对于我的 5 个存储过程来说应该足够了。为了安全起见,我扩展到 DW1000,它允许我最多 32 个并发查询(我使用的是 smallrc),但这对这个问题没有帮助。
这是我测试的方法(使用 DW1000)
我将 1000 条记录加载到 5 个单独的阶段表(stage1、stage2 等)中
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 等)。每个表具有与 stage 相同的 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 来执行存储过程。(这只是一个测试,所以请原谅样式/代码)
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# 代码时,每条语句都小于 1ms,直到我到达行 reader1 = cmd1.EndExecuteReader(result1); 在这里它将等待 4-5 秒,然后继续前进,之后的每一行都很快(<1ms)。
在此延迟期间,如果我从 sys.dm_pdw_exec_requests 运行 select *,我会看到所有 5 个请求都已排队并正在运行。如果我继续重新运行查询持续时间不断增加,那么突然(大约 5 秒)所有 5 个查询都说它们已完成。
在解释我做错了什么或 Azure SQL DW 在内部做什么时,我们将不胜感激。
谢谢