我对此有一个一般性的问题。很多时候,我们想更改以前插入大量数据的字段或排序规则的数据类型。考虑以下情况:
将varchar归类从utf8_general_ci转换为latin1_swedish_ci:据我所知,第一个具有多字节字符,第二个具有单字节字符。此转换是否正确处理存储的记录?并且这种转换是否会导致现有数据量的减少(也许是50%)?
int(10)到smallint(5)的转换:数据量是否正确减少到50%?
或例如:int(10)至unsigned int(10)-text至varchar(1000)-varchar(20)至char(10),...
显而易见,可以采取这些措施来提高效率,减少数据量并...
考虑我有一个具有1,000,000条记录的表。我想知道执行这样的操作是否会对存储的数据产生不良影响,或者是否会使涉及此表的将来插入和选择的性能降低。
更新:
当我谈论将utf8编码字符集更改为拉丁文时,当然我的字段的值是英语(很明显,如果有日语,它们将会丢失)。以此假设为前提,我要问的是结果表的大小和性能。
过早的优化是万恶之源。 您实际上是否要解决一些性能或存储问题? 如果是这样,那是什么?
很好,我的表大小正在快速增长,我想知道将utf8更改为拉丁语是否可以进行更改。 但我知道您的回答不会改变
Converting varchar collation from utf8_general_ci to latin1_swedish_ci: As I know the first has multibyte chars and the second singly byte ones. Does this conversion manipulate stored records correctly? And does this conversion lead to reduction of volume of existing data (maybe 50%)?
排序规则只是用于字符串比较的顺序,它(几乎)与用于数据存储的字符编码无关。我说这几乎是因为归类只能用于某些字符集,因此更改归类可能会强制更改字符编码。
在修改字符编码的程度上,MySQL会正确地将值重新编码为新的字符集,无论是从单字节变为多字节,反之亦然。请注意,对于列而言太大的任何值都将被截断。
如果新的字符类型具有可变长度,并且在新编码中使用比以前更少的字节来编码值,则表的大小当然会减小。
Conversion of int(10) to smallint(5): Does the volume of data reduce to 50% correctly?
INT和SMALLINT分别占据4和2个字节,而不管显示宽度如何:因此,表的大小将相应减小。
Or for example: int(10) to unsigned int(10) - text to varchar(1000) - varchar(20) to char(10), ...
INT占用4个字节,无论是否已签名,因此都不会发生变化;
TEXT和VARCHAR(1000)都占用L + 2个字节(其中L是该值的长度(以字节为单位)),因此不会有任何变化。
VARCHAR(20)占用L + 1个字节(其中L是该值的长度,以字节为单位),而CHAR(10)占用10w个字节(其中w是该字符集中最大长度字符所需的字节数),因此可以更改,但取决于存储的实际值和使用的字符编码。
请注意,取决于存储引擎,表大小的减小可能不会立即释放到文件系统中。
您提供了很好的信息。但是实际上在我的情况下,所有varchar字段值都是英文字符串(没有国际字符)。因此,如果我将排序规则更改为latin1_swedish_ci,表大小将如何变化?
如我的回答所述,整理几乎与编码无关。如果将编码从utf8更改为latin1(并且您的值仅包含ASCII字符),则不会有变化:在两种编码中,所有字符都仅以一个字节进行编码。如果您的值包含用utf8编码的字符且长度超过一个字节,则将相应减少(尽管如果latin1字符中不存在此类字符,则这些字符可能会被丢弃并替换为?占位符)组)。
如果是这样,为什么不总是使用utf8代替latin?还有其他考虑事项吗?
好吧,有些字符(例如重音符号)在latin1中只需要1个字节,在utf8中只需要2个字节。我几乎总是使用utf8。
A1。排序规则不会更改您的数据。它会更改查询中的排序顺序,并可能更改索引(?)。
A2。列中数据的长度将减少,但是每个表行始终有一些开销,并且您无法更改。此外,如果您的数据不是唯一的,则索引大小不会减少很多,因为索引看起来像这样:33-> {row1,row2,row3 ...},67-> {row9,row0,row7}并且每个行指针都比一个int大得多。
换句话说,如果您有一个包含一百个int行,没有很多索引的表,并且将所有这些列都更改为tinyint,那么您将看到显着的改进。如果只有一列,请不要打扰。
http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
http://dev.mysql.com/doc/refman/5.0/en/innodb-physical-record.html
A3。请仔细阅读文字与varchar。前者将数据与表行分开存储,后者在表行中分开存储。每个都有自己的含义。
ps。行和索引开销在很大程度上取决于您使用的数据库引擎。通常您应该使用innodb。但是对于只读任务,例如进行数据挖掘,myisam更加高效。
将varchar归类从utf8_general_ci转换为latin1_swedish_ci:可以减小表(文件)的大小,但是您可以不丢失拉丁符号,只能正确存储英语单词。
将int(10)转换为smallint(5)-将会减少数据量。 int(10)到unsigned int(10)的转换-不会减少。在这些情况下,您应该关心这些值,会得到一个错误-超出范围值。
将VARCHAR(20)转换为CHAR(10):CHAR用于始终具有相同长度(例如-10)的字符串,如果字符串长度不同,则使用VARCHAR数据类型。