我对这个问题很感兴趣。每次设计桌子时,我都会有这个疑问。以表帖子为例,它包含一个名为post_type的列,可以是以下值之一:
- post(varchar( 或 1(tinyint(
- 页面(varchar( 或 2(tinyint(
- 修订版(varchar(或3(tinyint(
问题是我应该为该列使用什么类型。varchar使查询结果会更直观,我不需要弄清楚 1/2/3 是什么意思。
至于tinyint,它的表现比varchar更好吗?
PS:我正在使用MySQL。
数据类型没有性能。它们是一种存储格式。
查询确实具有性能。因此,若要评估性能,应具体说明要测量的查询。
在仅按主键获取行的查询中,没有实际区别。InnoDB 将给定行的列放在页面上,因此一旦它将页面从磁盘提取到 RAM 中,所有列都可用。读取整数的 4 个字节与读取 8 个字节的字符串(如"修订版"(之间的差异微不足道。
SELECT post_type FROM posts WHERE post_id = 8675309;
如果您按行的post_type
值查找行,那么它变得更加重要,因为它需要做一些比较来评估每一行,看看它是否应该包含在结果中。根据行数以及是否有索引,字符串比较和整数比较之间的差异可能很重要。
SELECT ... FROM posts WHERE post_type = 'revision';
我创建了一个表,并用 100 万行填充>:
create table posts (
post_id serial primary key,
post_type_utf varchar(10),
post_type_bin varbinary(10),
post_type_int int
);
然后我计算了搜索整个表所需的时间:
select count(*) from posts where post_type_utf = 'revision';
+----------+
| count(*) |
+----------+
| 1048576 |
+----------+
1 row in set (0.24 sec)
mysql> select count(*) from posts where post_type_bin = binary 'revision';
+----------+
| count(*) |
+----------+
| 1048576 |
+----------+
1 row in set (0.15 sec)
mysql> select count(*) from posts where post_type_int = 1;
+----------+
| count(*) |
+----------+
| 1048576 |
+----------+
1 row in set (0.15 sec)
时间表明,搜索整数与搜索二进制字符串大致相同。
为什么 utf8 字符串更慢?因为每个字符串比较都必须根据为列定义的排序规则逐个字符地计算。二进制字符串比较只能使用memcmp()
在一个操作中比较整个字符串。
同样重要的是要考虑到,索引通常比您选择的数据类型更重要。索引会有所帮助,因为对特定post_type值的查询将仅检查匹配的行。
但在这种情况下,post_type只有几个不同的值,因此无论如何,索引中的搜索都可能匹配许多行。
如果你打算将它们用作数字,TINYINT(1)
肯定更好,因为mysql不需要进行不必要的转换。对于1-character
字符串,您可以使用CHAR(1)
或ENUM
.