在不少公司的mysql的开发规范中,会表中对blob ,text字段的情况,进行严格的审核。对含有大字段的表,有些公司的dba甚至需要开发总监级别以上的领导同意,才会在生产环境创建含大字段的表。 但大字段是否真的是洪水猛兽?大字段到底是如何存储在数据页中,以及大字段到底影响了哪些性能? 估计大多数的dba都没有进行过仔细的评估。
带着这些问题,作者分析了一下mysql的源码并行了简单的测试。
简单说一下包含大字段的表的的操作过程, 大致是这样。
a.首先通过函数ec 来判断是否需要转换为. 该函数的作用就是将字段非常长的字段(有个标准,大概是8K左右)从行中剥离,使其他字段组成的行变成可以按照普通行存放。
b.插入剥离大字段的行。
c.通过函数 插入该行的大字段。
因此,当一个表中虽然有大字段,但该大字段列存放的值长度比较小的时候,是不需要以的形式来存放的。虽然是一个含有大字段的行,但行的总体字符长度较短时,则按普通的行存放。 Blob 字段类型的基础类型,实际上跟的类型相同。所以,当某行的大字段存放的值的长度较长时,以独立存放,当某行的大字段存放的值的长度很小时,则以普通行的方式,跟其他字段一起存放。
同时,通过上面的分析,对于一个长度较长的行,当需要以方式存放时,实际上进行了两次存数据的操作。第一次是剥离了大字段后,其他字段的存放。 第二次是大字段的独立存放。
以下是ec的注释,请阅读。
/**************************************************************//**
Moves parts of long in entry to the big so that
the size of tuple drops below the size in the
. Moves data only from those which are not
to the place of the tuple in the index.
@ own: big , NULL if we are not able to
the entry , i.e., if there are too many fixed- or
short in entry or the index is */
*
ec(
/*===================*/
*index,/*!< in: index */
upd_t*upd,/*!< in/out: */
*entry,/*!< in/out: index entry */
ulint*n_ext)/*!< in/out: of
*/
…………………………………………………………………………………………………………………………………………..
…………………………………………………………………………………………………………………………………………………….
以下是 函数的注释,该函数的作用是存储需要独立存放的字段。 真正执行存放的函数为
/***************************************************************//**
Tries to the (off-page )
of a index entry.
@ or */
(
/*=============================*/
const *entry,/*!< in/out: index entry to */
const *,/*!< in: */
ulint*,/*!< in/out: rec */
**heap,/*!< in/out: heap */
*index,/*!< in: index */
const char*file,/*!< in: file name of */
#
const void*thd, /*!< in: , or NULL */
#endif /* */
)/*!< in: line of */
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
error = (
&pcur, 0, , , &mtr, );
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
下面是实际执行存放的函数的注释。
/*******************************************************************//**
the in to the and puts to
them in rec. The flags in rec will have to be set .
The are on pages from leaf node
file of the index tree.
TODO: If the the , it will not be redo , in
any mini-. be redo-, so that
will not fail when the was to the of
the file, in case the file was in the crash.
@ or */
(
/*============================*/
*pcur,/*!< in/out: a . if
is , then this can
be . */
const upd_t*upd,/*!< in: */
ulint*,/*!< in/out: () on
pcur. the ” ” flags
in will
to rec when this */
const *,/*!< in:
to be */
mtr_t*,/*!< in/out: mtr the
to the index. can be
and . */
enum )/*! in: code */
…….………………………………………………………………………………………………………………………………………………………………
通过上面的源码获知,对于包含大字段的, 需要多走一个存数据的操作,势必影响了的速度。
但对于查询呢,是否会有影响?
在做测试之前,作者的做一下猜想
a.因为大字段是独立存储,因此如果不查该大字段,也不使用大字段的字段作为结果集,在相同记录数下,含有大字段的表,跟不含有大字段的表,不管是走全表扫描,还是走索引查找,性能几乎一样。
b.如果对大字段全范围查找,大字段值的长度越长,长记录的数量越多,查找越慢。
c.建立两个表,一个表的其中一个字段是(100),另外一个表的其中一个字段为blob, 其他字段均相同,然后对这两个表进行插入完全相同的数据100万行,然后进行各种方式的数据查找,性能应该几乎一样。
限于排版,测试过程省略,有兴趣的朋友请自行测试。。。。
通过测试,以上猜想均被实验验证!
作者历史文章: