我管理的应用程序的数据库使用uid。这些uuid存储为char(36)
,具有utf8
字符集。从严格的性能角度来看,我知道这不是最佳的。一般的建议似乎是对uuid使用binary(16)
列。我不能更改数据类型,但可以更改字符集。
UUID中的字符可以是数字0到9,也可以是字母a到f。
通过将字符集从utf8
更改为ascii
,数据库的所有索引的总大小可能会减少几个gb。
应用程序连接到数据库,并显式地在连接字符串中设置字符编码和连接排序:characterEncoding=utf8&connectionCollation=utf8
。
我该怎么做(如果有的话)才能确保安全的"转换"?从utf8到ascii的uuid ?
首先,您可能无法获得将其转换为ASCII所希望的存储空间节省。uuid中的字符在ASCII和UTF8中都是一个字节。我不知道mysql的内部说它占用了多少空间。我怀疑它可能像varchar一样,有几个字节以字节表示字符串的长度,在这种情况下,您可能只在每个记录上节省几个字节。
如果您坚持要尝试,强烈建议您在尝试这样做之前对数据库进行备份。此外,构建一个小型测试数据库来测试您的更改也是明智的。谨慎的做法是确保使用数据库的应用程序在更改后仍然可以工作。可以使用简单的SQL语句更改表列的字符集和排序规则。您可能应该对数据库中所有类似的列执行相同的操作。在表或数据库级别更改它可能会对您的数据造成灾难性的影响。
您可能还应该更改应用程序,以便在设置或数据库恢复后以新的方式初始化数据库。
总之,对我来说,这听起来是一个高风险、低回报的改变。如果数据库中除了uuid之外几乎没有其他内容,并且您切换到二进制(16)而不是ASCII,那么您可以获得有意义的空间节省,但这也需要更改应用程序。标准uuid(相对于自制的uuid)只使用十六进制,它是ascii字符的子集,是utf8的子集。编码(位的排列方式)是相同的。因此,在转换过程中不会丢失数据。
有一件事要小心。如果您在uid上是JOINing
,请确保两个表中该列的CHARACTER SET
和COLLATION
是相同的。否则,将会有很大的性能损失。(MySQL没有足够的智能来理解你只是十六进制)
还要检查排序规则——如果是..._ci
,那么"a"== & &;等等。这将是有益的,如果你可能需要折叠。(..._bin
将a..f与a..f区别对待)
在InnoDB中,VARCHAR
或CHAR
, ascii或utf8mb4,几乎任何长度至少为36,都是一样的。
是的,一定要备一个,以防万一。
对于大型表,uuid有不可避免的性能问题。我在这里讨论:http://mysql.rjweb.org/doc.php/uuid