有的时候你可能需要索引字符数非常多的列。这会让你的索引非常大并且很慢。一个策略就是模拟hash索引。前一部分已经说过了。但是有的时候这种方法也不是很好。将要怎么做。
一般可以用索引前一部分的一些字符的方法来节省空间并且可以获得好的性能。这样可以使你的索引使用更少的空间,但是这样会降低选择性。索引的选择性(Index selectivity)是索引值的数量和表中行的数量(#T)的一个比率。范围是1/#T到1.索引的选择性越高越好,因为这样当匹配的时候,MySQL就会过滤掉更多的行。一个唯一索引的选择性1,这是最好的了。
一个前缀的索引对于好的性能来说,它的选择性已经足够了。如果你对BLOB和TEXT列进行索引,或者非常长的VARCHAR列,你必须定义前缀索引,因为MySQL不允许索引它们的全部长度。
技巧就是选择一个列的前缀,并且这个前缀的长度能有个好的选择性,但是又可能节约更多的空间。索引前缀所带来的索引效果应该尽可能的接近索引全部长度所带来的效果。
要知道一个好的前缀的长度,找到最常见的值并且把它们和最常见的前缀进行比较。看下如下例子
CREATE TABLE sakila.city_demo(city VARCHAR(50) NOT NULL);
INSERT INTO sakila.city_demo(city) SELECT city FROM sakila.city;
-- Repeat the next statement five times:
INSERT INTO sakila.city_demo(city) SELECT city FROM sakila.city_demo;
-- Now randomize the distribution (inefficiently but conveniently):
UPDATE sakila.city_demo
SET city = (SELECT city FROM sakila.city ORDER BY RAND( ) LIMIT 1);
现在我们有一个示例数据集。结果并不是真是分布的,并且我们使用了RAND(),因此结果是变化的,但是对于此练习并不会有什么影响。首先我们找到出现频率最高的cities.
mysql> SELECT COUNT(*) AS cnt, city
-> FROM sakila.city_demo GROUP BY city ORDER BY cnt DESC LIMIT 10;
发现每个城市出现的次数范围为45-65.现在我们在查找频率出现最高的前缀。从3个字母的前缀开始。
+-----+------+
| cnt | pref |
+-----+------+
| 483 | San |
| 195 | Cha |
| 177 | Tan |
| 167 | Sou |
| 163 | al- |
| 163 | Sal |
| 146 | Shi |
| 136 | Hal |
| 130 | Val |
| 129 | Bat |
+-----+------+
每个前缀都出现了很多次。因此有太多的唯一前缀要多于唯一全长度的city names.接下来的方法就是提高前缀的长度直到这个前缀的选择性接近于全长度的列。通过实验发现前缀长度为7最为合适。
mysql> SELECT COUNT(*) AS cnt, LEFT(city, 7) AS pref
-> FROM sakila.city_demo GROUP BY pref ORDER BY cnt DESC LIMIT 10;
+-----+---------+
| cnt | pref |
+-----+---------+
| 70 | Santiag |
| 68 | San Fel |
| 65 | London |
| 61 | Valle d |
| 49 | Hiroshi |
| 48 | Teboksa |
| 48 | Pak Kre |
| 48 | Yaound |
| 47 | Tel Avi |
| 47 | Shimoga |
+-----+---------+
另一种计算前缀的方法就是,计算整个列的选择性并且使前缀的选择性 接近于这个值。下面就是计算整列的选择性
mysql> SELECT COUNT(DISTINCT city)/COUNT(*) FROM sakila.city_demo;
+-------------------------------+
| COUNT(DISTINCT city)/COUNT(*) |
+-------------------------------+
| 0.0312 |
+-------------------------------+
如果前缀的选择性接近与0.031。那么这个前缀长度就是合适的。下面就是找到合适前缀的语句。
mysql> SELECT COUNT(DISTINCT LEFT(city, 3))/COUNT(*) AS sel3,
-> COUNT(DISTINCT LEFT(city, 4))/COUNT(*) AS sel4,
-> COUNT(DISTINCT LEFT(city, 5))/COUNT(*) AS sel5,
-> COUNT(DISTINCT LEFT(city, 6))/COUNT(*) AS sel6,
-> COUNT(DISTINCT LEFT(city, 7))/COUNT(*) AS sel7
-> FROM sakila.city_demo;
+--------+--------+--------+--------+--------+
| sel3 | sel4 | sel5 | sel6 | sel7 |
+--------+--------+--------+--------+--------+
| 0.0239 | 0.0293 | 0.0305 | 0.0309 | 0.0310 |
+--------+--------+--------+--------+--------+
这个查询显示出,7字符的前缀长度最佳。
看平均的选择性也不是太好的主意。你也需要考虑最坏情况的选择性的时候。平均的选择性可能使你看到4,5长度的前缀也是不错的。但是如果你的数据是不均匀的。这可能就出现问题了。如果你查看最常见城市的前缀为4的出现数目,你就会清楚的发现不均匀的数据。
mysql> SELECT COUNT(*) AS cnt, LEFT(city, 4) AS pref
-> FROM sakila.city_demo GROUP BY pref ORDER BY cnt DESC LIMIT 5;
+-----+------+
| cnt | pref |
+-----+------+
| 205 | San |
| 200 | Sant |
| 135 | Sout |
| 104 | Chan |
| 91 | Toul |
+-----+------+
4个字符,出现前缀的频率比全部值的频率要高。因此选择性就要比平均选择性要低很多。如果你有真实的数据,你可能看到这种影响非常大。比如,你在真实的城市名称中创建4个字符前缀的索引,会带来非常差的选择性。
对于我们的示例数据,我们已经发现合适的值了。来看看怎样在这个列创建索引:
mysql> ALTER TABLE sakila.city_demo ADD KEY (city(7));
前缀的索引可以使索引更小并且更快,但是它也有明显的缺点。MySQL不能在ORDER BY或GROUP BY语句中使用前缀索引,也不能把它们作为覆盖索引进行使用。
分享到:
相关推荐
### 高效MySQL查询加速指南:索引策略、查询优化、性能调优 在数据库管理和开发领域中,MySQL因其灵活性和高效性而受到广泛欢迎。然而,在面对大规模数据集时,即使是性能强大的MySQL也可能遇到查询速度慢的问题。...
5.3.2前缀索引和索引选择性153 5.3.3多列索引157 5.3.4选择合适的索引列顺序159 5.3.5聚簇索引162 5.3.6覆盖索引171 5.3.7使用索引扫描来做排序175 5.3.8压缩(前缀压缩)索引177 5.3.9冗余和重复索引178 ...
此外,我们还需要注意索引字段的选择,例如使用前缀索引,避免使用 low cardinality 的字段创建索引等。 无法使用索引的场景 在无法使用索引的场景中,我们需要注意通过索引扫描的记录数超过 30%,变成全表扫描的...
对于redo日志和binlog的刷盘策略,如innodb_flush_log_at_trx_commit和sync_binlog,应根据应用的事务安全性和性能需求进行调整。内存分配方面,可以选用jemalloc或tcmalloc等高效内存管理库。 Schema优化主要包括...
选择合适的MySQL版本至关重要,新版本往往包含更多的功能和性能改进。对于特定环境,如使用Intel处理器的服务器,可以考虑使用Intel优化过的MySQL版本,如通过Intel C++编译器编译的版本,这能够进一步提高查询性能...
在Oracle数据库中,Schema是一个非常重要的概念,它代表了数据库对象的集合,这些对象包括但不限于表格、视图、序列、存储过程、同义词、索引、簇和数据库链接等。Schema是逻辑结构,直接与数据库的数据相关,帮助...
- 优化索引列顺序,选择性高的列放在前面,以提高查询效率。 - 覆盖索引的使用可以减少数据表的访问,提高查询速度。 4. **查询性能优化**: - 分析查询效率时,关注是否检索过多数据,以及是否充分利用索引来...
- **对象命名**:所有对象(如表、字段等)均需加上schema前缀,例如`create table tt.t_test(a int, b int, c varchar(20));`。 - **表引擎**:创建数据表时指定引擎为InnoDB,以支持事务处理并提高并发能力。...
总的来说,DorisDB作为新一代的极速MPP数据库,集高性能、易用性、灵活性和扩展性于一身,适用于报表查询、多维分析、实时分析和即席查询等多种应用场景,是构建高效数据仓库和BI系统的理想选择。通过与Flink、Kafka...
MySQL 5.7版本引入了许多新特性、性能优化和改进,以提高数据存储、管理和查询的效率。以下是一些关键知识点: 1. **InnoDB存储引擎**:MySQL 5.7默认使用InnoDB存储引擎,它支持事务处理、行级锁定以及外键约束,...
2. **Performance Schema增强**:Performance Schema是MySQL的监控和性能分析工具,5.7版本提供了更多的系统状态变量和表,以便更详细地监控系统资源使用情况和查询执行。 3. **JSON支持**:MySQL 5.7增加了对JSON...
以上知识点涵盖了MySQL的基础知识,包括跨平台连接、存储引擎、日志管理、客户端功能、复制机制、备份策略、索引使用、查询优化、事务处理、数据库监控和性能调整等多个方面。理解和掌握这些知识点对于MySQL的日常...
1. **SQL语句执行流程**:当提交一个SQL语句时,MySQL会经历解析、预处理、优化和执行四个阶段。解析阶段会检查SQL语法;预处理阶段处理SQL中的变量和常量;优化阶段选择最佳执行计划;执行阶段执行查询并返回结果。...
- **Performance Schema**:一个新的监控和性能分析工具,帮助管理员了解系统资源的使用情况。 - **线程池**:提高多用户并发访问时的效率。 2. **JDBC 驱动**: - **Java Database Connectivity (JDBC)** 是 ...
在存储引擎方面,为了提升大规模集群的稳定性和性能,TiDB 优化了 Raft 的流程,引入 Region Merge、Raft Learner 等新特性;优化热点调度机制,统计更多的信息,并根据这些信息做更合理的调度;优化 RocksDB 的性能...
常见的索引类型包括唯一索引、聚集索引和非聚集索引(或普通索引),前缀索引则是对字符串列的部分字符创建的索引。 12. `EXPLAIN`语句用于分析SQL执行计划,如果`KEY`列值显示为实际使用的索引,那么这个SQL语句就...