MySQL插入,在PHP中比C++;,这是预期的吗? 最近我已经被做了一些速度检查,所以我可以判断是否更快地使用PHP/PHP CLI或C++来插入一定数量的行到数据库中。

MySQL插入,在PHP中比C++;,这是预期的吗? 最近我已经被做了一些速度检查,所以我可以判断是否更快地使用PHP/PHP CLI或C++来插入一定数量的行到数据库中。,php,c++,mysql,performance,Php,C++,Mysql,Performance,在开始之前,让我告诉你一些细节,以便一切都清楚: php部分通过Apache运行,直接在浏览器中请求 正在SSD驱动器上运行的硬盘驱动器测试。我想在常规驱动器中速度会慢一些。这台机器本身没什么特别的,大约有六年的历史了 所有插入都是通过准备好的语句完成的。我们使用PHP上的myQLII和mysql LCPPPCON(MySQL C++连接器,Oracle提供)。 所有插入都是逐项完成的。我知道我们可以把它们叠加起来,但我们在这里测试 在PHP中通过MICTIME和C++中的报头显示时间。 当然

在开始之前,让我告诉你一些细节,以便一切都清楚:

  • php部分通过Apache运行,直接在浏览器中请求
  • 正在SSD驱动器上运行的硬盘驱动器测试。我想在常规驱动器中速度会慢一些。这台机器本身没什么特别的,大约有六年的历史了
  • 所有插入都是通过准备好的语句完成的。我们使用PHP上的myQLII和mysql LCPPPCON(MySQL C++连接器,Oracle提供)。
  • 所有插入都是逐项完成的。我知道我们可以把它们叠加起来,但我们在这里测试
  • 在PHP中通过MICTIME和C++中的报头显示时间。
  • 当然,代码本身并不是等价的。稍后再谈
  • 所有文本均为UTF-8格式。里面有俄语、汉语、阿拉伯语、西班牙语、英语和各种疯狂的东西。mysql表的格式为utf8_4mb
  • < L> > C++代码的编号是使用STD::vector和-O2级别的结果,用G++编译(向量优于图,无序的映射和STD::数组)。
因此,这是一个过程:

  • 连接到数据库
  • 打开一个包含N行的文本文件
  • 读取文件的一行
  • 在分隔符上拆分行
  • 使用分割线的某些部分来获取插入值(例如,第0、第1和第3个索引)
  • 将这些部分发送到准备好的语句以插入它们
  • 重复此操作,直到文件完全读取
这两个代码的工作完全符合预期。结果如下:

php:

  • 5000个条目:1.42-1.27秒
  • 20000个条目:5.53-6.18秒
  • 50000条记录:14.43-15.69秒
c++:

  • 5000条记录:1.78-1.81秒
  • 20000个条目:7.19-7.22秒
  • 50000条记录:18.52-18.84秒
PHP优于C++,因为文件中的行增加了…首先,我怀疑行拆分函数:php中的拆分是用“explode”完成的。这个算法对于C++来说是天真的。容器通过引用传递,其内容会动态更改。容器只被遍历一次。我确保容器“reserves()”所有必要的空间(记住,我最终选择vectors)都是固定的。容器在主函数上创建,然后通过代码通过引用传递。它永远不会被清空或调整大小:只有它的内容会改变

template<typename container> void explode(const std::string& p_string, const char p_delimiter, container& p_result)
{
    auto it=p_result.begin();
    std::string::const_iterator beg=p_string.begin(), end=p_string.end();
    std::string temp;

    while(beg < end)
    {
        if( (*beg)==p_delimiter)
        {
            *(it)=temp;
            ++it;
            temp="";
        }
        else
        {
            temp+=*beg;
        }

        ++beg;
    }

    *(it)=temp;
}
模板无效分解(常量std::string和p_字符串、常量char p_分隔符、容器和p_结果)
{
auto it=p_result.begin();
std::string::const_迭代器beg=p_string.begin(),end=p_string.end();
std::字符串温度;
while(beg
如前所述,所执行的任务是等效的,但生成它的代码不是。C++代码具有用于控制MySQL交互的常用尝试块。至于其余部分,主循环运行直到EOF达到,并且每次迭代检查插入失败(无论是在C++和PHP中)。 <>我看到C++在处理文件和内容方面大大胜过PHP,所以我期望在这里也适用。不知何故,我怀疑分裂算法,但可能只是数据库连接器较慢(仍然,当我禁用数据库交互PHP仍然处理得更快)或我的代码是低于…p>

从剖析开始,GPROF对C++代码吐露:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  ns/call  ns/call  name    
 60.00      0.03     0.03    50000   600.00   600.00  void anc_str::explotar_cadena<std::vector<std::string, std::allocator<std::string> > >(std::string const&, char, std::vector<std::string, std::allocator<std::string> >&)
 40.00      0.05     0.02                             insertar(sql::PreparedStatement*, std::string const&, std::vector<std::string, std::allocator<std::string> >&)
  0.00      0.05     0.00        1     0.00     0.00  _GLOBAL__sub_I__ZN7anc_str21obtener_linea_archivoERSt14basic_ifstreamIcSt11char_traitsIcEE
每个样本计数为0.01秒。
%累积自我总数
时间秒秒呼叫ns/呼叫ns/呼叫名称
60.00 0.03 0.03 50000 600.00 600.00无效anc_str::explotar_cadena(标准::字符串常量和,字符,标准::向量和)
40.00 0.05 0.02插入器(sql::PreparedStatement*,std::string const&,std::vector&)
0.00 0.05 0.00 1 0.00 0.00全球子系统和标准体系结构基本流程图
其中,“explotar_cadena”是“explode”,而“insertar”是“拆分此行并设置准备好的语句”。正如你所看到的,60%的时间都花在那里(这并不奇怪……它运行了50000次,并且做了这种疯狂的拆分操作)。“obtener_linea_archivo”只是“请将下一行转储到字符串中”

在没有mysql交互的情况下(只需加载文件、读取行并拆分它们),我就可以得到以下度量值:

php

  • 5000条记录:0.019-0.036秒
  • 20000条记录:0.09-0.10秒
  • 50000条记录:0.14-0.17秒
c++

  • 5000条记录:0.07-0.10秒
  • 20000条记录:0.25-0.26秒
  • 50000条记录:0.49-0.55秒
好吧,这两次都很好,对于现实生活来说几乎不值得注意,但我还是很惊讶。。。所以这里的问题是:我应该期待这个吗?。有经验的人愿意帮忙吗

提前谢谢


<>编辑:这里是一个快速链接到一个精简版本包含输入文件,C++代码和PHP代码[]。请注意,没有sql交互:只有文件打开、字符串拆分和时间测量。请原谅这段断章取义的代码、半西班牙语注释和变量名,因为这是匆忙完成的。另外,请注意上面的gprof结果:我不是专家,但我认为我们正在试图找到一种更好的拆分字符串的方法。

其中的一部分可能与每种语言中使用的驱动程序/接口有关。例如,使用PHP/MySQL,您可能会发现