InnoDB big-end问题和一个小优化

 

1、背景

  InnoDB引擎存储int类型时使用big-endian, MySQL使用litter-endian, 导致一个问题是在两个层之间拷贝int类型数据的时候必须用一个循环来处理,而不能直接memcpy 在引擎层返回数据量很大的情况下,很耗cpu

 

       在报表类的一些查询中,会访问大量的数据。我们有个项目的一个查询需要访问到1.4wbigint,这个时候cpu的消耗就体现出来了。

 

2、相关代码

目前使用的转换代码就是使用循环。

row_sel_field_store_in_mysql_format这个函数的作用是把数据从InnoDB格式转成MySQL格式,

 

如下:

ptr = dest + len;                                            

                                                             

for (;;) {                                                    

        ptr--;                                               

        *ptr = *data;                                        

        if (ptr == dest) {                                   

                break;                                       

        }                                                    

        data++;                                              

}

 

这里如果是bigint就需要循环8次。

 

       反过来的转换代码在row_mysql_store_col_in_innobase_format,也是类似的需要一个循环。

 

3、改进和效果

这一坨循环,O3编译以后的汇编代码下,如果是bigint,需要40条指令。而显然我们使用的时候,intbigint会很多。

因此考虑当len=48的时候,使用bswapbswapq实现。

 

修改后再用oprofile观察上面说到的一个统计查询压力下的结果,发现row_sel_field_store_in_mysql_format这个函数cpu占用率从50%下降到44%.

 

DB的多数情况下压力还是在io,因此这个改进的效果需要在特定场景下才能体现。 最近跟Oracle InnoDB工程师讨论的时候了解到会有一些专门针对减少汇编结果做的优化,就凑热闹把这个提了。

Patch内容: http://bugs.mysql.com/file.php?id=18018&text=1 基于5.5.22

你可能感兴趣的:(mysql,性能,汇编,big-endian)