在MySQL或Postgres中使用混合表字符集时会出现性能问题吗?
我正在处理一个数据库,它的表具有不同的字符集。因为它是一个大数据库,我想知道它是否会导致性能问题。是的,DB通常进行的值比较是连接和比较整数,但是除了某些字符集占用的空间较大之外,我们在使用具有不同字符集的表时还会遇到其他性能问题吗?如果使用不兼容的排序规则进行字符串比较,这些比较不能在字符串列上使用索引。我在对字符串列进行联接时看到过这种情况,并且联接的表具有不同的排序规则(当然,如果它们也具有不同的字符集,那么它们也是不同的排序规则) 但您说过联接是在整数列上,而不是字符串列上。因此,在您的情况下,连接不应该是一个问题在MySQL或Postgres中使用混合表字符集时会出现性能问题吗?,mysql,database,postgresql,character-encoding,collate,Mysql,Database,Postgresql,Character Encoding,Collate,我正在处理一个数据库,它的表具有不同的字符集。因为它是一个大数据库,我想知道它是否会导致性能问题。是的,DB通常进行的值比较是连接和比较整数,但是除了某些字符集占用的空间较大之外,我们在使用具有不同字符集的表时还会遇到其他性能问题吗?如果使用不兼容的排序规则进行字符串比较,这些比较不能在字符串列上使用索引。我在对字符串列进行联接时看到过这种情况,并且联接的表具有不同的排序规则(当然,如果它们也具有不同的字符集,那么它们也是不同的排序规则) 但您说过联接是在整数列上,而不是字符串列上。因此,在您的
如果表字符集与会话字符集不匹配,则在查找字符串列时也可能出现性能问题 示例:我的表是用utf8mb4定义的,但我将会话设置为utf8,所以字符串文本将是utf8。看起来是无害的改变,对吧
mysql> set names utf8;
mysql> explain select * from mytable where text = 'abc123';
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
| 1 | SIMPLE | mytable | NULL | ref | text | text | 83 | const | 1 | 100.00 | NULL |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
我想utf8字符串“abc123”有一个明确的方法可以升级为utf8mb4,以匹配它所比较的列
但是,如果我强制执行utf8mb4不支持的特定排序规则,我发现它必须执行表扫描并逐个比较行,而不是索引查找:
mysql> explain select * from mytable where text = 'abc123' collate utf8_general_ci;
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+
| 1 | SIMPLE | mytable | NULL | ALL | NULL | NULL | NULL | NULL | 10 | 100.00 | Using where |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------------+
隐式排序规则和显式排序规则之间有区别。假设我将会话设置为使用没有到utf8mb4的清晰路径的内容:
mysql> set names latin1;
mysql> explain select * from mytable where text = 'abc123';
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
| 1 | SIMPLE | mytable | NULL | ref | text | text | 83 | const | 1 | 100.00 | NULL |
+----+-------------+---------+------------+------+---------------+------+---------+-------+------+----------+-------+
到目前为止还不错,但如果我明确说明了排序规则:
mysql> explain select * from mytable where text = 'abc123' collate latin1_general_ci;
ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (latin1_general_ci,EXPLICIT) for operation '='
底线是,您应该使用相同的字符集和排序规则,以使您的生活更轻松。将其用于所有表和会话
在当今时代,很难找到使用utf8mb4以外的任何东西的理由
p.S.空间不应该是个问题。UTF-8字符集允许使用多字节字符,但不能扩展适合单个字节的字符大小。UTF-8是一种可变宽度字符编码。因此ASCII范围(0-127)中的字符无论如何都存储在一个字节中。详细阅读,它有一个很好的解释。MySQL: 对于存储为字符串(
CHAR
或VARCHAR
)的邮政编码(postal\u code)),大多数字符集都同样有效。但是,当在这样一列上加入时,排序规则必须相同
- 如果相同,则可以使用该列上的索引
- 如果不是,则索引是无用的,查询必须扫描整个表
由于排序规则包括字符集,因此也会强制字符集相同
排序规则的选择很小。但是,如果字符串中可能有字母(邮政编码、国家/地区编码等),则需要决定是否强制表(和用户查询)使用特定的大小写
- 排序规则
…\u bin
将案例视为不同:“de”与“de”(德国)不匹配
- 排序规则
…\u ci
是“不区分大小写”的,因此它们将匹配
您可以优化列字符集,例如zipcode utf8不好,更好的选择是latin1或ascii,甚至可以节省磁盘空间,制作更小的表。你需要储存网页内容吗?utf8现在可能是你的选择!谢谢你的评论!事实上,这更多的是关于速度而不是空间(我知道它们是相关的,但我想关注的是不受占用空间影响的性能)感谢您的努力和完整的答案!