最近在开发中才发现的一个问题,用C 或者C++语言通过编程形式操作 远程的MySQL 数据库,(数据库放在一个空间中)它的效率都很低,测试:插入5000条(只有三个属性 code varchar(20) username(20) address(40))这样的数据,不管是通过MyODBC(5.1)还是通过 MySQL C API 的编程形式操作数据库都得花上 500 多秒,汗死我了,正常的通过JDBC访问的话也只需要5秒左右的,这个测试在 Mysql 5.0 和 MySQL 5.5都测试过,也都分别以 MyODBC 和 MySQL C API 的形式测试过,结果都是差不多的都在130 - 150秒之间徘徊,那位高手曾今遇到过这个问题了。或者懂得怎么解决的。。请发表一下见解,(最后我想说,不会是语句的问题的:测试语句就是一句 Insert Into tablename(xxx,xxx,xxx) vulues('xx','xxxx','xxxx') 插入语句,这个插入语句至于一个 for(int i=0;i<5000;i++) 中,所以不要考虑是编写代码的问题了。。代码就简单的插入语句。请高手们指点谢谢由于昨天高手wwwwa的方法 在 insert into 操作前加入 BeginTransaction()  insert into ...
  commitTransaction() 这对本地的数据库是起作用了。。但是远程的MySQL数据库,插入操作还是很慢,(500秒啊)不要考虑这个网络问题了网络再怎么的慢也不会有500秒那么夸张的,,那位高手。。请再指点指点

解决方案 »

  1.   

    你一次插入这么多语句都是一次提交的,试试在你的循环中加i mod 100 =0 commit;看是否还有效率问题
      

  2.   

    my.ini 中加 skip-name-resolve  试试。 
      

  3.   

    回复 :biandongfeng:好的。。我试一试。。这个试过了。。效率一样一样的。。都要44秒那样子个人觉得如果数据量不是太大几十万条或者上百万条都没有必要像biandongfeng说的那样。。如果有更好的建议请随时留言
      

  4.   

    回复:qiying1988这对操作远程数据库有什么关系呢?
      

  5.   

    我要补充一个问题:我的本地MySQL数据库就是应为加了 事务才会变快的,而本地事务缺省的的数据库引擎就是 InnoDB (这个引擎支持事务)而远程的MySQl数据库缺省的数据库是MyISAM(不支持事务)我想是不是改变一下数据引擎就好了呀。。如果改变了数据引擎对已有的数据表影响有多大了。。看来我明天得好好看看这其中的奥妙。。这个可不敢贸然测试了。。因为远程数据库的数据不能轻易动的真汗。。那位高手有更好的建立可以直接发表发表
      

  6.   

    测试插入1条,花多少时间,如果也是很多,那说明就是连接花了很多时间,可能存在name lookup
    就加上skip-name-resolve 
      

  7.   

    回复:aleng18:  create table tb_test(
                   id int auto_increment,
                   code varchar(20) not null,
                   username varchar(20) not null,
                   address  varchar(40) not null,
                   constraint pk_testcode primary key(id));
    我想在建表的时候指定数据表所用的的数据库引擎,InnoDB 这样会不会好些呢?
    回复:trainee:
    if(db.Open(strConnection))
    {
    TRY
    {
    db.BeginTransaction();
    CString sql("");
    sql="insert into tba_test(code,username) Values('sdfdsfdsfdssdfsd','张三家')";
    db.Execute(sql);
    db.CommitTransaction();
    db.Close();
    }
    CATCH(CFileException,e)
    {
    return;
    }
    }如果是把数据库连接也算进去的话,单次插入时间为 3.23秒,经测试数据连接时间为2.5秒左右,不包括数据库连接时间单次插入如果用事务的话每次都基本在 1 秒左右,不用事务就在0.2秒那样子,(可能是网咯问题,也出现过0.02秒的)
    我想这根本就是数据引擎问题,等我把在建表的时候把数据库引擎指定一下,再告诉大家答案,还有一个问题:
    就是 skip-name-resolve  加载My.ini的任意位置都可以么?以后回帖子,写得详细些。。谢谢(毕竟大牛们面对的都是我们这些。。菜鸟呀。。哈哈)。。thanks
      

  8.   

    使用 SqlBulkCopy 类!
    详细请看msdn!
      

  9.   

    估计是引擎的问题。
    代码可优化的地方:使用动态bind列值
      

  10.   

    代码就那一个Insert Into 语句,要是引擎有问题的话,那为什么本地数据库插入如此之快呢?用的都是 INNODB 数据库引擎,这是我想不明白的地方,远程跟本地的差别肯定是会有的。。但是绝对不是 这500 - 0.5秒的差别,(就算是网络再差,也不至于此)我倒是可以百度一下如何动态bing列值。。谢谢 “iihero”的回复。。
      

  11.   

    上面已经给出主要的代码了再给一次:
    CADODatabase db;
    CString temp("");
    CString strConnection = _T("Driver={MySQL ODBC 5.1 Driver};Server=myRemoteServeripcom;Database=mydb;User=username;Password=123456;Option=3");

    double timeTol;        // 总共消耗的时间
    int64 timeStart = 0;   // 开始操作时的时间
    __int64 timeStop;
    SYSTEMTIME systemtime;//记录执行SQL语句前的时间
    if(db.Open(strConnection))
    {
    TRY
    {
                GetLocalTime(&systemtime);
        SystemTimeToFileTime(&systemtime, (FILETIME*)&timeStart);
        db.BeginTransaction();
        CString sql("");
        sql="insert into tba_test(code,username,address) Values('sdfdsfdsfdssdfsd','张三家','宿舍对方立即离开')";
        for(int i=0;i<5000;i++)
            db.Execute(sql);
        db.CommitTransaction();
        db.Close();
    }
    CATCH(CFileException,e)
    {
         return;
    }
    END_CATCH
    }
    //记录执行SQL语句后的时间
    GetLocalTime(&systemtime);
    SystemTimeToFileTime(&systemtime, (FILETIME*)&timeStop);
     //记录执行SQL语句总共消耗的时间
    timeTotal = ((double)(timeStop - timeStart) / 10000000);
    temp.Format("执行远程SQL语句成功\r\n\r\n总共消耗 = %8.3f秒",timeTotal);
    MessageBox(temp);
    用的CADODatabase 的一个别人封装好的数据库操作类,(个人已经排除了是这个类导致数据库访问效率低下的问题)  “ACMAIN_CHM” 还有什么不够详细的么?有更好的想法随时欢迎留言
      

  12.   

    用了你的代码,有一个警告信息。mysql> show create table tb_test;
    +---------+---------------------------------------------------------------------
    --------------------------------------------------------------------------------
    -----------------------------------------------------------------------------+
    | Table   | Create Table                                                                             |
    +---------+---------------------------------------------------------------------
    --------------------------------------------------------------------------------
    -----------------------------------------------------------------------------+
    | tb_test | CREATE TABLE `tb_test` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `code` varchar(20) NOT NULL,
      `username` varchar(20) NOT NULL,
      `address` varchar(40) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
    +---------+---------------------------------------------------------------------
    --------------------------------------------------------------------------------
    -----------------------------------------------------------------------------+
    1 row in set (0.01 sec)mysql> insert into tba_test(code,username) Values('sdfdsfdsfdssdfsd','XXXXxxxx')
    ;
    ERROR 1146 (42S02): Table 'csdn.tba_test' doesn't exist
    mysql> insert into tb_test(code,username) Values('sdfdsfdsfdssdfsd','XXXXxxxx');Query OK, 1 row affected, 1 warning (0.03 sec)mysql> show warnings;
    +---------+------+----------------------------------------------+
    | Level   | Code | Message                                      |
    +---------+------+----------------------------------------------+
    | Warning | 1364 | Field 'address' doesn't have a default value |
    +---------+------+----------------------------------------------+
    1 row in set (0.00 sec)mysql> select * from tb_test;
    +----+------------------+----------+---------+
    | id | code             | username | address |
    +----+------------------+----------+---------+
    |  1 | sdfdsfdsfdssdfsd | XXXXxxxx |         |
    +----+------------------+----------+---------+
    1 row in set (0.00 sec)mysql>
      

  13.   

    没有用你的C测试,直接使用了 C# + MySQL .NET connector. 并没有你所说的情况。创建如下表格,并事先插入记录后并删除,以防止磁盘空间分配引起的开销。
    mysql> show create table tb_test;
    +---------+--------------------------------------
    | Table   | Create Table
    +---------+--------------------------------------
    | tb_test | CREATE TABLE `tb_test` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `code` varchar(20) NOT NULL,
      `username` varchar(20) NOT NULL,
      `address` varchar(40) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
    +---------+--------------------------------------
    1 row in set (0.01 sec)mysql> select count(*) from tb_test;
    +----------+
    | count(*) |
    +----------+
    |    10002 |
    +----------+
    1 row in set (0.00 sec)mysql> delete from tb_test;
    Query OK, 10002 rows affected (0.27 sec)mysql> select count(*) from tb_test;
    +----------+
    | count(*) |
    +----------+
    |        0 |
    +----------+
    1 row in set (0.00 sec)mysql>
    执行代码
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using MySql.Data.MySqlClient;namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Start Connection ... "+DateTime.Now.ToString());            string sMySQLConnStr = "Database='csdn';Data Source='localhost';User Id='root'";
                MySqlConnection mysqlCnn = new MySqlConnection(sMySQLConnStr);
                mysqlCnn.Open();            MySqlCommand mysqlCmd = new MySqlCommand("insert into tb_test(code,username) Values('sdfdsfdsfdssdfsd','XXXXxxxx')", mysqlCnn);            Console.WriteLine("Start Insert .... "+DateTime.Now);
                for(int i=0;i<5000;i++)
                    mysqlCmd.ExecuteNonQuery();
                Console.WriteLine("Insert accomplished "+DateTime.Now);            Console.ReadKey();
            }
        }
    }执行结果Start Connection ... 6/17/2011 2:39:18 PM
    Start Insert .... 6/17/2011 2:39:18 PM
    Insert accomplished 6/17/2011 2:39:29 PMStart Connection ... 6/17/2011 2:42:56 PM
    Start Insert .... 6/17/2011 2:42:56 PM
    Insert accomplished 6/17/2011 2:43:06 PM
      

  14.   

    建议你用上个帖子的方法,INNODB+事务+插入+提交的方法
      

  15.   

    我本来是想上个贴子的方法能解决本地跟远程的,但是上个帖子的方法都能解决本地的MySQL数据,一旦远程访问就歇菜了
    回复:ACMAIN_CHM C#语言我没有试过,但是如果没有说错的话,C#用的是.net技术吧,我也用过一些LinqTOSQL 但是问题是现在是C++/C反问远程数据的数据库出了问题,并不是C#语言访问远程数据库出了效率低下的问题,同样感谢大牛们的回帖。。期待更多的回复。。问题依旧处在未解决之中。。
      

  16.   

    自己用代码连接MYSQL,再运行,看看速度如何
      

  17.   

    [Quote=引用 15 楼 acmain_chm 的回复:]
    没有用你的C测试,直接使用了 C# + MySQL .NET connector. 并没有你所说的情况。你这个代码测试的是不是远程数据库的时间,不要随便拿个本地数据库来测试。远程数据库,我也按照你的代码测试了。。慢得不像样!!!!
      

  18.   

    你说的JDBC用了5秒也是远程数据库吗?
      

  19.   


    我想你这个测试肯定是本地的一个Mysql数据库的,由于建表的时候数据库存储引擎是 INNODB的,我不知道你的数据库引擎采用什么类型的,但是如果的数据库引擎也是INNODB的话,你所写的代码执行效率也是很低的,因为你缺少了事务,(这个我已经测试过了,没有事务,操作本地数据库跟远程差不多,如果有了事务,那么时间大概就是1-2秒)有事务的代码如下(C#)
              //  string sMySQLConnStr = "Database='db_Test';Data Source='MyServer';User Id='root';Password='xxxx'";
                MySqlConnection mysqlCnn = new MySqlConnection(sMySQLConnStr);
                mysqlCnn.Open();
                MySqlTransaction Tran = mysqlCnn.BeginTransaction();
                MySqlCommand mysqlCmd = new MySqlCommand("insert into tba_test(code,username,address) Values('sdfdsfdsfdssdfsd','张三的李','撒开绿灯飞机撒旦立刻解放')", mysqlCnn);
                mysqlCmd.Transaction = Tran;
                for (int i = 0; i < 5000; i++)
                    mysqlCmd.ExecuteNonQuery();
                mysqlCmd.Transaction.Commit();
                MessageBox.Show("SUCCESS");
    很感谢你的回答,个人觉得你这个回答本身有小问题,首先,我可以确定,你测试的不是远程的MySQL数据库(或许你所用的MySQL Server 缺省的数据库引擎不一样,而你写出来的代码就是有相当好的效率,但是,在我这边测试,结果却不是这样的)再次感谢、、、
      

  20.   

    你在操作远程MYSQL时,有多少用户连接?你的配置是怎样的
      

  21.   

    这是一个桌面应用程序,不是wwwwb所认为的B/S架构的应用程序,因为远程的MySQL数据库都是买别人的空间(空间自带的MySQL数据库)由于访问量不是很大,具体用户连接我不知道多少。但是我可以确定,不多,至于wwwwb我的配置是怎么样?这里问得我不知道怎么回答,配置具体指代那个方面?应为上面的回答我说过了。远程的数据库缺省的数据库引擎是 MyISAM 的,但是我建表的时候却是指定了 数据库引擎为 INNODB (远程数据库支持 INNODB )我个人觉得就是远程数据库的配置上有问题,但是又不知道具体问题在哪里
      

  22.   

    感觉你应该问问空间提供商,MYSQL是什么版本、配置是怎样的
      

  23.   

    过去好几天了都差不多影响结贴时间了。。问题依旧在哪里,没有实质性的解决,我只有当作是MySQL Server 的问题了,其实也可以这么一说,毕竟同样的代码本地MySQL数据操作是正常的,而同样的代码相对远程MySQL Server就出现效率慢得让人受不了的问题了我相信,也只能相信是远程MySQL Server的问题了。。问了空间MySQL 供应商,只是说插入数据太多了。。属于正常,具体他们也没有测试过(我想这扯蛋的就是在这里了 )依然感谢上面参与的各位,平心而论,虽然问题没有彻底得到解决,但是你们的宝贵意见,对我以后的工作依然起到了不少的作用。。准时结贴给分