mysql - 在 MySQL 或 Postgres 中使用混合表字符集时会出现性能问题吗?
问题描述
我正在研究一个具有不同字符集的表的数据库。由于它是一个大型数据库,我想知道它是否会导致性能问题。是的,数据库通常进行的通常值比较是 JOIN 并且完成了整数比较,但是除了某些字符集占用的更大空间之外,我们还会遇到具有不同字符集的表的任何其他性能问题吗?
解决方案
如果您使用不兼容的排序规则进行字符串比较,则这些比较不能使用字符串列上的索引。我已经看到在对字符串列执行 JOIN 时发生这种情况,并且加入的表有不同的排序规则(当然,如果它们也有不同的字符集,它们也是不同的排序规则)。
但是您说您的联接是在整数列上,而不是在字符串列上。因此,在您的情况下,连接应该不是问题。
如果您的表字符集与会话字符集不匹配,则在对字符串列进行查找时也会遇到性能问题。
示例:我的表是用 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 以外的任何东西的理由。
PS Space 应该不是问题。UTF-8 字符集允许多字节字符,但它们不会扩展适合单个字节的字符大小。UTF-8 是一种可变宽度字符编码。因此,ASCII 范围 (0-127) 中的字符无论如何都存储在一个字节中。有关详细信息,请阅读wikipedia 上的 UTF-8,它有一个很好的解释。
推荐阅读
- css - CSS媒体查询覆盖移动优先的先前样式
- c++ - 如何为两种已经存在的类型创建重载?
- c# - 如何通过 C# 代码从 gcloud Bucket 重命名对象名称?
- docker - Docker 中的 rq:“无法解析 Redis 连接”与其他工作的 Redis 连接
- c# - 如何将我的 Azure Web 应用 API 访问限制为仅对我的 Xamarin.Forms 应用程序的访问?
- postgresql - Postgresql UPDATE 查询适用于 Windows 但不适用于 Ubuntu
- python - 根据邮政编码在真实地图上显示数据
- database - laravel 数据库播种一对多,计数器需要重置
- c - 关于将数组类型转换为指针
- java - Java Hibernate Apache Derby - 表/视图不存在