string 和 int 列(table 设计)之间真的存在性能差异吗?
Is there really performance different between of string and int cloumn(table design)?
我对这个问题很感兴趣。每次设计一个table,我都有这个疑惑。以tableposts为例,它包含一个名为post_type的列,可以是一个以下值:
- post(varchar) 或 1(tinyint)
- 页数(varchar)或 2(tinyint)
- 版本(varchar) 或 3(tinyint)
问题是我应该为该列使用什么类型。 varchar让查询结果更直观,不用去搞清楚1/2/3是什么意思
至于tinyint,它比varchar性能好吗?
PS:我正在使用 MySQL。
如果您要将它们用作数字,TINYINT(1)
绝对更好,因为 mysql 不需要进行不必要的转换。对于 1-character
字符串,您可以使用 CHAR(1)
或 ENUM
.
数据类型没有性能。它们是一种存储格式。
查询确实有性能。因此,要评估性能,您应该具体说明要测量的查询。
在仅通过主键获取行的查询中,没有实际区别。 InnoDB 将给定行的列一起保存在一个页面上,因此一旦它将页面从磁盘提取到 RAM 中,所有列都可用。读取 4 个字节的整数与读取 8 个字节的字符串(如 'revision')之间的区别是微不足道的。
SELECT post_type FROM posts WHERE post_id = 8675309;
如果您按 post_type
值查找行,那么它会变得更重要一些,因为它需要做一些比较来评估每一行,看看它是否应该包含在结果中.根据行数以及您是否有索引,字符串比较和整数比较之间的区别可能很重要。
SELECT ... FROM posts WHERE post_type = 'revision';
我创建了一个 table 并填充了超过 100 万行:
create table posts (
post_id serial primary key,
post_type_utf varchar(10),
post_type_bin varbinary(10),
post_type_int int
);
然后我计时搜索整个需要多长时间table:
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 只有几个不同的值,因此索引中的搜索很可能会匹配许多行。
我对这个问题很感兴趣。每次设计一个table,我都有这个疑惑。以tableposts为例,它包含一个名为post_type的列,可以是一个以下值:
- post(varchar) 或 1(tinyint)
- 页数(varchar)或 2(tinyint)
- 版本(varchar) 或 3(tinyint)
问题是我应该为该列使用什么类型。 varchar让查询结果更直观,不用去搞清楚1/2/3是什么意思
至于tinyint,它比varchar性能好吗?
PS:我正在使用 MySQL。
如果您要将它们用作数字,TINYINT(1)
绝对更好,因为 mysql 不需要进行不必要的转换。对于 1-character
字符串,您可以使用 CHAR(1)
或 ENUM
.
数据类型没有性能。它们是一种存储格式。
查询确实有性能。因此,要评估性能,您应该具体说明要测量的查询。
在仅通过主键获取行的查询中,没有实际区别。 InnoDB 将给定行的列一起保存在一个页面上,因此一旦它将页面从磁盘提取到 RAM 中,所有列都可用。读取 4 个字节的整数与读取 8 个字节的字符串(如 'revision')之间的区别是微不足道的。
SELECT post_type FROM posts WHERE post_id = 8675309;
如果您按 post_type
值查找行,那么它会变得更重要一些,因为它需要做一些比较来评估每一行,看看它是否应该包含在结果中.根据行数以及您是否有索引,字符串比较和整数比较之间的区别可能很重要。
SELECT ... FROM posts WHERE post_type = 'revision';
我创建了一个 table 并填充了超过 100 万行:
create table posts (
post_id serial primary key,
post_type_utf varchar(10),
post_type_bin varbinary(10),
post_type_int int
);
然后我计时搜索整个需要多长时间table:
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 只有几个不同的值,因此索引中的搜索很可能会匹配许多行。