当插入数十万行时,MySQL与MS Access相比非常慢

时间:2010-05-09 10:09:46

标签: mysql ms-access

我目前首先在MS Access Table上向MySQL表添加数十万行数据。

我首先尝试使用MS Access,花了不到40秒。 然后我尝试使用相同的源和相同的表结构到MySQL,它花了6分40秒。那是慢了1000%!!!

数据库服务器具有更好的性能是神话吗?

3 个答案:

答案 0 :(得分:3)

执行数以千计的独立INSERT将会非常缓慢地运行。由于MySQL是一个多用户的事务性数据库,因此在每次查询期间都会有比Access更多的事情。 SQL Server上的每个INSERT操作都执行以下步骤:

  1. 解码并解析查询。
  2. 打开表格进行书写,必要时建立锁定。
  3. 插入新行。
  4. 如有必要,请更新索引。
  5. 将表保存到磁盘。
  6. 理想情况下,您希望尽可能少地执行步骤1,2,4和5。 MySQL有一些功能可以帮助你。

    预备您的查询

    通过准备要重复使用的查询,您只需执行一次步骤1。方法如下:

    PREPARE myinsert FROM 'INSERT INTO mytable VALUES (?, ?, ?)';
    SET @id = 100;
    SET @name = 'Joe';
    SET @age = 34;
    EXECUTE myinsert USING @id, @name, @age;
    SET @id = 101;
    SET @name = 'Fran';
    SET @age = 23;
    EXECUTE myinsert USING @id, @name, @age;
    # Repeat until done
    DEALLOCATE PREPARE myinsert; 
    

    在mysql.com网站上阅读有关PREPARE的更多信息。

    使用交易

    将几个(或几百个)INSERT组合到一个事务中。服务器每个事务只需执行一次步骤2,4和5。

    PREPARE myinsert FROM 'INSERT INTO mytable VALUES (?, ?, ?)';
    
    START TRANSACTION;
    SET @id = 100;
    SET @name = 'Joe';
    SET @age = 34;
    EXECUTE myinsert USING @id, @name, @age;
    SET @id = 101;
    SET @name = 'Fran';
    SET @age = 23;
    EXECUTE myinsert USING @id, @name, @age;
    # Repeat a hundred times
    COMMIT;
    
    START TRANSACTION;
    SET ...
    SET ...
    EXECUTE ...;
    # Repeat a hundred times
    COMMIT;
    
    # Repeat transactions until done
    
    DEALLOCATE PREPARE myinsert;
    

    详细了解transactions

    从文件中加载表

    不要进行数千次INSERTS,而是批量上传数据。如果您的数据位于分隔文件(例如CSV)中,请使用LOAD DATA语句。

    LOAD DATA LOCAL INFILE '/full/path/to/file/mydata.csv' INTO TABLE `mytable` FIELDS TERMINATED BY ',' LINES TERMINATED BY '\r\n';
    

    这是LOAD DATA上MySQL页面的链接。

答案 1 :(得分:2)

通常,数据库最重要的性能方面不是插入数据的速度有多快,而是查询数据的速度有多快。我认为MySQL具有比MS Access更强大的优化器,可以更好地利用索引。这方面的一个例子是loose index scan,它可以为某些类型的查询提供10倍或更高的速度。

此外,用于插入数据的方法可能会影响插入所需的时间。例如,与许多单独的插入语句相比,使用批量插入通常会更快。在插入时禁用索引并在之后再次启用它们可以提高性能。

答案 2 :(得分:1)

MySQL是否提供任何SQL跟踪工具,以便您可以看到Access正在发送它?根据我通过ODBC使用Access与SQL Server的经验,我可以告诉你,Jet通过批量插入做出了一些看似奇怪的决定。它的作用是为每条记录发送一个插入,而不是为所有记录发送批量插入。这使它大大减慢,但它确实意味着它不能将SQL Server与长更新(以及相应的表锁等)捆绑在一起。

从插入的角度来看,它是愚蠢的,但从成为一个好的客户端/服务器公民的角度来说是聪明的 - 它允许SQL Server决定如何序列化所请求的命令并将它们与来自其他用户的命令交错。这意味着锁定比在批量插入时更短。

使用SQL Server,您可以使用ADO执行此操作并强制它以批处理方式处理插入。我不知道有没有办法用MySQL做到这一点。

要考虑的一件事:

如果源表和目标表都在MySQL中,则直通查询应该使其完全由MySQL处理。