【问题标题】:Strange behaviour on writing to db while using service broker使用服务代理时写入数据库的奇怪行为
【发布时间】:2017-06-26 19:37:30
【问题描述】:

我正在测试服务代理外部激活器和基于轮询的客户端,代表它们各自的处理速度性能。

对于外部激活器,我构建了一个命令行应用程序,当某个表发生任何更改并写入同一个数据库时,它会收到通知。 exe里面的代码如下所示

 private static void ProcessRequest()
    {
        using (var connection = new SqlConnection(ServiceConstant.ConnectionString))
        {
            connection.Open();
            do
            {
                using (var tran = connection.BeginTransaction())
                {
                    //Get a message from the queue
                    byte[] message = QueueProcessorUtil.GetMessage(ServiceConstant.QueueName, connection, tran, ServiceConstant.WaitforTimeout);
                    if (message != null)
                    {
                        MessageReceiving = true;
                        try
                        {
                            //Write it to the db
                            ProcessMessage(message);
                        }
                        catch (Exception ex)
                        {
                            logger.Write("Fail: " + ex);
                        }
                        tran.Commit();

                    }
                    else
                    {
                        tran.Commit();
                        MessageReceiving = false;
                    }
                }
            }
            while (MessageReceiving);
        }
    }

当我向队列中插入 20 条消息时,插入所有消息的总持续时间约为 10ms

当我提取上面的 ProcessMessage 函数时,它将消息写入数据库到另一个单独的控制台应用程序,然后调用此函数 20 次,如下所示,这次大约需要 50ms

class Program
    {
        static void Main(string[] args)
        {
            for (var i = 1; i <= 20; i++)
            {
                string message = "mm";
                ProcessMessaage(message);
            }
        }
    }

ProcessMessage函数

string sql = @"INSERT INTO [Workflow].[dbo].[TestOrderLog]([OrderId],[RecordTime]) 
                        VALUES (@orderId, GETDATE()) SELECT SCOPE_IDENTITY()";

                using (SqlConnection con = new SqlConnection(ConfigurationManager.AppSettings["SqlConnection"].ToString()))
                using (SqlCommand com = new SqlCommand(sql, con))
                {
                    con.Open();
                    com.CommandType = CommandType.Text;
                    com.Parameters.AddWithValue("@orderId", 1);
                    try
                    {
                        var result = com.ExecuteScalar();
                        var id = (result != null) ? Convert.ToInt32(result) : 0;
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                    con.Close();
                }

我不明白也很惊讶,尽管在外部激活器代码的循环中存在昂贵的处理块(查询消息),但编写 db 比在控制台应用程序代码中编写纯循环要快。

为什么在循环中纯插入比在外部激活器 exe 实例的代码中插入要慢?

旁注,在 EAService.config 文件中,&lt;Concurrency min="1" max="1" /&gt;

【问题讨论】:

  • 好的,请解释您的要求。您是说在控制台应用程序代码中编写 db 比编写纯循环需要更快吗?那么写入数据库比使用控制台应用程序更快吗?不知道这里的问题是什么。
  • @Namphibian 实际上我写了所有东西,外部激活器触发 exe,此代码中的循环(ProcessRequest 函数)然而,以某种方式比控制台应用程序更快地插入到 db。如果您检查间隔,每毫秒插入第一个记录 4 到 8 条记录,另一方面,为第二种情况仅插入一条记录需要 3 毫秒。这到底是怎么发生的?上面第一个代码中的循环也查询到了数据库的第一位。
  • 阅读 O Notation 并尝试找出哪个 O 系数较低。
  • 据我所知,步数越少,算法越快,所以,第二个应该更快,但让我计算一下O因子看看。
  • 等一下,你在第一个而不是第二个使用事务?

标签: c# sql-server sqlconnection service-broker


【解决方案1】:

这是我的一个荒谬的错误,第一个是编译和部署运行代码 第二个是在Visual Studio中使用调试器运行的,所以间隔在没有调试器的情况下正常运行。

【讨论】:

  • 是的,这就是问题所在。
  • @Namphibian 是的,我快疯了,顺便说一句谢谢你的努力:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-15
  • 1970-01-01
  • 1970-01-01
  • 2016-06-16
  • 2021-10-01
  • 2014-04-24
  • 1970-01-01
相关资源
最近更新 更多