【问题标题】:MySQL Performance vs MSSQL PerformanceMySQL 性能与 MSSQL 性能
【发布时间】:2016-07-07 10:12:27
【问题描述】:

我正在尝试比较 MySqlMS SQL Server 的基本 insert 性能。使用 Business Management Studio 执行以下 MSSQL 查询需要 1 秒:

declare @i int
set @i=1

while (@i<1000)
begin
    insert into empmast 
        (name) values ( 'Client ' + cast(@i as varchar(10) ))
    set @i = @i + 1
end
go

WorkBench 中的类似查询需要 40 秒才能执行。这是查询:

DELIMITER $$
DROP PROCEDURE IF EXISTS xproc_loop_test$$
CREATE PROCEDURE xproc_loop_test()
BEGIN
  DECLARE int_val INT DEFAULT 0;
  test_loop : LOOP
  IF (int_val > 1000) THEN
  LEAVE test_loop;
END IF;

SET int_val = int_val +1;
insert into empmast (name) values ( 'Client ' + int_val );
END LOOP; 
END;

这是否意味着 MySQL 在数据插入方面要慢得多?

【问题讨论】:

  • 为什么在一种情况下创建存储过程而在另一种情况下只有一个循环。基本相同的代码不会给你一个更公平的结果吗?
  • @jonny Mysql 只允许存储过程(和函数)中的循环
  • @P.Salmon mySql 耗时更长的原因可能与存储过程也被编译有关。

标签: mysql sql-server


【解决方案1】:

是和否 - 我怀疑这更多地与插入的时间和频率有关。例如,在您的查询的以下(固定)版本中,我在进入循环之前将自动提交设置为 0(关闭)并在循环终止后提交。在我的电脑上,这将执行时间从 34 秒缩短到 0.25 秒

DROP PROCEDURE IF EXISTS xproc_loop_test;

DELIMITER $$
CREATE PROCEDURE xproc_loop_test()
BEGIN

  DECLARE int_val INT DEFAULT 0;
    set autocommit = 0;
  test_loop : LOOP
  IF (int_val > 998) THEN
        LEAVE test_loop;
    END IF;

    SET int_val = int_val +1;
    insert into empmast (name) values (concat( 'Client ' , int_val) );

END LOOP;
commit; 
END $$;
delimiter ;

【讨论】:

  • 谢谢鲑鱼,去吧。在所有插入之后提交确实会带来惊人的性能变化。但请记住,在 SQL Server 中,我不需要将提交设置为结束。
  • SQL server 为你做这件事——这是 mysql 和 sql server 之间的行为差​​异之一。
【解决方案2】:

对于这个用例,显然 MySQL 比 SQL Server 慢得多。根据我的经验,MySQL 通常比这快得多。而且,SQL Server 通常更慢。我的 MariaDB 10.0.x 实例在这方面并不慢,花了 32 毫秒。

许多因素会影响批量插入性能。当用户插入行时,RDMS 服务器会做很多不可见的工作,例如构建 BTREE 索引和维护事务数据的完整性。

从简单的测试用例(尤其是顺序值)推断出关于性能的一般性结论是不明智的。顺序值插入有时可能需要 BTREE 重新平衡,这可能很耗时。

在 MySQL 中,将插入循环包装在事务中会产生很大的性能差异。像这样:

BEGIN TRANSACTION;
test_loop : LOOP
  IF (int_val > 998) THEN
    LEAVE test_loop;
  END IF;

  SET int_val = int_val +1;
  insert into empmast (name) values (concat( 'Client ' , int_val) );

END LOOP;
COMMIT;

为什么?因为您已经告诉 MySQL,它可以构建一批记录以一次性插入所有记录,并且可以一次性更新您的索引。

如果您使用程序插入一百万行,通常明智的做法是将它们包装在每个几千行的事务中。

【讨论】:

    猜你喜欢
    • 2016-09-11
    • 1970-01-01
    • 2012-07-11
    • 2010-10-08
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多