31

我的平台:

PHP 和 mySQL

我的情况:

我遇到了一种情况,我需要在表的一个列中存储用户选择的值。现在我的选择是:

  1. 将 Column 声明为 char(1) 并将值存储为 'y' 或 'n'
  2. 或者将 Column 声明为 tinyint(1) 并将值存储为 1 或 0
  3. 如此声明的该列也可以被索引以在应用程序中使用。

我的问题:

所以我想知道,以上两种类型中的哪一种:

  1. 访问该列时会导致更快的查询速度(为简单起见,请不要混合其他查询或访问其他列)。

  2. 是存储和访问数据的最有效方式吗?为什么?

  3. 如果列被索引以及何时不被索引,访问速度如何变化?

我的理解是,由于 char(1) 和 tinyint(1) 只占用 1 个字节空间,在这种情况下存储空间不会成为问题。那么剩下的就是访问速度了。据我所知,数字索引比其他任何东西都更快、更有效。但我认为,这里的案子很难决定。肯定想听听你在这方面的经验。

先感谢您。

4

8 回答 8

43
                       Rate insert tinyint(1) insert char(1) insert enum('y', 'n')
insert tinyint(1)     207/s                --            -1%                  -20%
insert char(1)        210/s                1%             --                  -19%
insert enum('y', 'n') 259/s               25%            23%                    --
                       Rate insert char(1) insert tinyint(1) insert enum('y', 'n')
insert char(1)        221/s             --               -1%                  -13%
insert tinyint(1)     222/s             1%                --                  -13%
insert enum('y', 'n') 254/s            15%               14%                    --
                       Rate insert tinyint(1) insert char(1) insert enum('y', 'n')
insert tinyint(1)     234/s                --            -3%                   -5%
insert char(1)        242/s                3%             --                   -2%
insert enum('y', 'n') 248/s                6%             2%                    --
                       Rate insert enum('y', 'n') insert tinyint(1) insert char(1)
insert enum('y', 'n') 189/s                    --               -6%           -19%
insert tinyint(1)     201/s                    7%                --           -14%
insert char(1)        234/s                   24%               16%             --
                       Rate insert char(1) insert enum('y', 'n') insert tinyint(1)
insert char(1)        204/s             --                   -4%               -8%
insert enum('y', 'n') 213/s             4%                    --               -4%
insert tinyint(1)     222/s             9%                    4%                --

在大多数情况下,似乎enum('y', 'n')插入速度更快。

                       Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1)        188/s             --               -7%                   -8%
select tinyint(1)     203/s             8%                --                   -1%
select enum('y', 'n') 204/s             9%                1%                    --
                       Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1)        178/s             --              -25%                  -27%
select tinyint(1)     236/s            33%                --                   -3%
select enum('y', 'n') 244/s            37%                3%                    --
                       Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1)        183/s             --              -16%                  -21%
select tinyint(1)     219/s            20%                --                   -6%
select enum('y', 'n') 233/s            27%                6%                    --
                       Rate select tinyint(1) select char(1) select enum('y', 'n')
select tinyint(1)     217/s                --            -1%                   -4%
select char(1)        221/s                1%             --                   -2%
select enum('y', 'n') 226/s                4%             2%                    --
                       Rate select char(1) select tinyint(1) select enum('y', 'n')
select char(1)        179/s             --              -14%                  -20%
select tinyint(1)     208/s            17%                --                   -7%
select enum('y', 'n') 224/s            25%                7%                    --

选择也似乎是enum. 代码可以在这里找到

于 2010-01-08T14:01:55.250 回答
35

我认为您应该使用创建列ENUM('n','y')。Mysql 以最佳方式存储这种类型。它还将帮助您在字段中仅存储允许的值。

ENUM('no','yes')您还可以在不影响性能的情况下使其更加人性化。因为字符串'no'和每个定义'yes'只存储一次。ENUMMysql 只存储每行值的索引。

ENUM另请注意按列排序:

ENUM 值根据枚举成员在列规范中列出的顺序进行排序。(换句话说,ENUM 值是根据它们的索引号排序的。)例如,对于 ENUM('a', 'b'),'a' 在 'b' 之前排序,但对于 ENUM,'b' 在 'a' 之前排序('b','a')。

于 2010-01-07T20:43:21.280 回答
11

使用 tinyint 是更标准的做法,可以让您更轻松地检查字段的值。

// Using tinyint 0 and 1, you can do this:
if($row['admin']) {
    // user is admin
}

// Using char y and n, you will have to do this:
if($row['admin'] == 'y') {
    // user is admin
}

我不是 MySQL 内部工作的专家,但直觉上觉得检索和排序整数字段比字符字段快(我只是觉得 'a' > 'z' 比 0 > 1 工作更多) ,并且从计算的角度来看似乎更加熟悉,其中 0 和 1 是标准的开/关标志。所以整数的存储似乎更好,感觉更好,并且更容易在代码逻辑中使用。0/1 对我来说是明显的赢家。

您可能还注意到,在某种程度上,这也是 MySQL 的官方立场,来自他们的文档

BOOL、BOOLEAN:这些类型是 TINYINT(1) 的同义词。零值被认为是错误的。非零值被认为是真的。

如果 MySQL 将 TINYINT(1) 等同于 BOOLEAN,这似乎是可行的方法。

于 2010-01-07T20:43:06.293 回答
4

要确定它,您应该对其进行基准测试。或者知道从整个项目的宏观角度来看,这可能并不重要。

Char 列具有编码和排序规则,比较它们可能涉及编码之间的不必要切换,所以我的猜测是 int 会更快。出于同样的原因,我认为更新 int 列上的索引也更快。但同样,这并不重要。

CHAR可以占用多个字节,具体取决于您选择的字符集和表选项。有些字符可能需要三个字节来编码,因此 MySQL 有时会保留该空间,即使您只使用yand n

于 2010-01-07T20:46:17.810 回答
3

他们都将如此接近,以至于无关紧要。如果您觉得必须在 SO 上提出这个问题,那么您就过度优化了。使用最合乎逻辑的一个。

于 2010-01-07T20:48:07.547 回答
1

如果在 MySQL 中创建表时指定类型BOOLBOOLEAN作为列类型,它将创建列类型为TINYINT(1). 大概这是两者中更快的一个。

文档

还:

我们打算在未来的 MySQL 版本中根据标准 SQL 实现完整的布尔类型处理。

于 2010-01-07T20:50:16.850 回答
1

虽然我的预感是 TINYINT 上的索引会比 CHAR(1) 上的索引更快,因为没有字符串处理开销(排序规则、空格等),但我没有任何事实可以证明支持这一点。我的猜测是,没有值得担心的显着性能差异。

但是,因为您使用的是 PHP,所以存储为 TINYINT 更有意义。使用 1/0 值等同于使用trueand false,即使它们作为字符串返回给 PHP,也可以这样处理。您可以简单地if ($record['field'])将结果作为布尔检查执行,而不是一直在“y”和“n”之间转换。

于 2010-01-07T20:50:53.853 回答
1
 TINYINT    1 Byte
CHAR(M)     M Bytes, 0 <= M <= 255

有什么不同吗?

于 2010-01-07T20:54:10.997 回答