本文是《数据库设计那些事》的笔记和思考。
有如下几种情形:
- 当字段可选择多个类型时(比如生日字段,可以用时间戳,即整数类型,可以用字符串 类型,也可以用日期 类型):整数、二进制 优于 日期 优于 字符串。
原因:
一、在对数据进行比较(查询条件、JOIN条件及排序)操作时:同样的数据,字符处理往往比数字要慢。
二、在数据库中,数据处理以页为单位,比如 mysql 16k字节一个页。而列的长度越小,在一个页中存储的数据就会越多。在加载相同多的数据的时候,如果列越小,加载的页就会越少。I/O的性能就会提高。
- 当字段要在 char 和 varchar 之间取舍的时候,有如下几条原则:
- 如果列中所要存储的数据长度是确定,且基本一致的,比如身份证字符串,则应该使用char;否则应该使用 varchar。
- 如果列中的最大数据长度小于50个字节,且这个列使用频繁,则应该使用char。如果列中的最大数据长度小于50个字节,但是很少使用,则基于减少空间和节省I/O的角度考虑,还是可以使用 varchar的。
- 一般不宜定义大于50字节的char类型列。
解释:每一个 varchar 的列,除了存储数据需要的字节之外,还需要额外的字节存储数据的实际长度。在检索数据时,也需要确定数据的起止位置。
所以,对于 utf-8 编码的字符串,超过15个字符,就要考虑使用 varchar。
不过生活总是充满各种反转和意外的,对于char 和 varchar 应该如何选择,我看到一篇博文上说和存储引擎的选择有很大关系。说的似乎也很有道理:
InnoDB 存储引擎 建议使用VARCHAR类型。
对于InnoDB数据表,内部的行存储格式没有区分固定长度和可变长度列(所有数据行都使用指向数据列值的头指针),因此在本质上,使用固定长度的CHAR列不一定比使用可变长度VARCHAR列简单。因而,主要的性能因素是数据行使用的存储总量。由于CHAR平均占用的空间多于VARCHAR,因此使用VARCHAR来最小化需要处理的数据行的存储总量和磁盘I/O是比较好的。
这就很让人纠结了。到底该听谁的?外事不决问google,然后我就在stackoverflow 那发现一个很有启发性的建议:
MySQL’s indexing is good enough that the difference in performance is tiny. It’s only when tables get large ( meaning on the order of 10**9 rows or more ) that the performance difference between VARCHAR() and CHAR() starts to be meaningful.
It’s smarter to spend your precious development time making your app nice enough that you have a chance of attracting gazillions of users. And when you have them, you probably can get a really competent database administrator to help you fix your minor inefficiencies.
大意就是,mysql的速度已经很快了,尤其是使用了索引之后,选 char 和 varchar 对于性能的提升根本微不足道。老老实实把你的 app 做大才是重点,别整天整这些有的没的。
这个兄弟说话很对我胃口啊,看起来也是个全栈工程师。是贫道执迷了。这个知识点先跳过。
- 对于decimal和 float类型有如下原则:
- decimal用于存储精确数据,而float只能用于存储非精确数据。故精确数据只能选择用decimal类型。
- 由于float类型的存储开销一般比decimal小,故非精确类型优先选择float。