高性能mysql-数据类型与表结构优化(一)

来自于高性能mysql的一部分总结。

1.schema和数据类型优化

选择数据类型的原则:
1. 小。
小,占磁盘小,占内存小,占cpu少。
比如varchar字段,varchar(10)和varchar(255),存储“a”的时候,虽然都占两个字节,但是在从磁盘读取到内存的时候,内存却要准备255字符对应的大小的内存块,比如排序操作,或者临时表的时候。因为内存并不知道varchar字段到底真正存了一个多大的数据,所以只能最坏打算。
2. 简单
整型比字符串简单,字符串有字符集、校对规则。
使用日期类型而不是字符串。
使用整形存储ip,而不是字符串。
3. 避免null
null需要更多存储空间,需要多一个字节标记是否为null。
mysql对null需要特殊的处理。

1.1 数据类型

1.1.1 整型类型

tinyint、smallint、mediumint、int、bigint,分别占8、16、24、36、64位存储空间。
对于int(11)这样规定大小是无意义的,因为int不管规定多大的大小,都不会影响其占的字节数以及大小范围,只会对一些mysql交互工具显示产生影响。

1.1.2 浮点型

Decimal除了存储小数之外,可以存储比bigint还大的数。

float、double和decimal都可以表示小数,但是float和double使用的是标准的浮点运算,cpu直接使用原声的浮点运算,所以可能会导致结果的不精确。(比如java,double a = 1.0f - 0.1f = 0.8999999这种现象)。但是decimal是精确计算,mysql服务器自身实现了对decimal的精确计算处理。decimal占用空间大,decimal(18,9),整数位占4个字节,小数位占4个字节,小数点占1个字节。

1.1.3 字符串类型

varchar 比char更节省空间,除非row_format=fix定长控制(几乎不会)。
varchar需要1到2个字节,记录字符串长度,小于255长度,用1个字节记录,大于,用2个字节记录。
varchar是变长的,所以update操作的时候,可能导致页分裂
varchar(255)和varchar(10)存储“a”这个字符,磁盘上占用的空间是一样的,但是当读取到内存,进行排序或者生成临时表的时候,占用的空间是不一样的,内存对于varchar(255)不知道其实际存储了多大的字符,所以会按最坏的情况,分配255个空间,所以为了节省cpu和内存,varchar需要尽可能小。

char存储,会把末尾空格删掉,比较的时候会填充空格进行比较(这不分存储引擎,因为这个操作是mysql服务层做的),同样大小的字符,char比varchar节省空间,因为varchar需要1或2个字节记录字符串长度。

还有一个和char和varchar性质类似的是,binary和varbinary,binary存储的是二进制字符串。

对于随机字符串,比如md5()或uuid(),因为大小随机,所以,插入位置是随机的,会造成随机访问,页分裂、聚簇索引碎片等,所以insert会慢,select 也会慢,因为逻辑位置相邻的数据物理位置不同,局部性原理失效(局部性原理是说,磁盘预读几页数据缓存起来,局部性原理认为,访问这个位置的数据,很可能会访问这个位置附近的数据)。
对于uuid这种随机字符串,可以使用unhex()函数转成16字节的数字存储,检索的时候再hex()转换回来。

blob和text类型
因为内存不知道其实际存储了多少个字符,所以极其好性能,会使用磁盘临时表,可以使用substring()截取成字符串,来使用内存临时表。
当然,这种字段,尽可能不用。

1.1.4 枚举

枚举排序,使用的枚举对应的整形,而不是字符串,所以如果对此有要求的时候,定义枚举的时候,按照字符串的顺序定义。
枚举的一个不好的地方是:修改枚举的时候,使用的是alter table操作。所以我觉得对于枚举,还是直接使用int类型,在服务层做转换比较好。

1.1.5 日期类型

不管什么日期类型,都只能精确到秒,如果需要存储微妙,则可以使用bigint存储微妙级别时间戳,或者double存储秒之后的部分。
timestamp时间范围是1970到2038,而且依赖时区,服务器、客户端连接都有时区设置。

1.1.6 位数据类型

bit,存储的是二进制,检索的时候查出来的是这个二进制表示的ascii值。
避免使用这种类型。

如果要存储boolean类型,true or false,可以使用可为null的char(0),char(0)占用一个位,可以表示两种情况,null或空字符串。(我觉得没必要)

1.2 schema设计陷阱

1.太多的列

mysql服务层通过存储引擎api,以行缓冲格式拷贝数据,然后在服务层解码成各个列,所以如果一行有太多的列的话,行缓冲数据解码成各个列的消耗是很大的。

2. 太多的关联

mysql限制了每个关联最多只能是61张表。太多关联的弊端不必说。

1.3.反范式

以更新代码换取查询性能,以及排序性能。
子表的统计数据记录在父表,省的每次查询都要count()统计子表。

1.4. 缓存表和汇总表

汇总表,把一些定时汇总,得到一个不精确的数据,加快查询。精确查询则,统计汇总表数据的和,加上汇总表数据到真实时间这个区间的数据和。

缓存表:把一个表的某些字段,缓存到另一个表中。

1.5 加快alter table的速度

线上alter table会锁住整个表,可以使用新结构创建一个空表,然后数据迁移完之后,重命名表替换旧表。有工具可以帮助做这一系列操作。比如:online-schema-change

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容