MySQL 模拟条件目录
程序员文章站
2022-05-30 18:47:17
...
MySQL 模拟条件索引 我们知道,MySQL 不支持条件索引。 什么是条件索引呢? 条件索引就是在索引列上根据WHERE条件进行一定的过滤后产生的索引。 这样的索引有以下优势: 第一点, 比基于这个列的全部索引占用空间来的
MySQL 模拟条件索引我们知道,MySQL 不支持条件索引。 什么是条件索引呢? 条件索引就是在索引列上根据WHERE条件进行一定的过滤后产生的索引。 这样的索引有以下优势:
第一点, 比基于这个列的全部索引占用空间来的小。
第二点, 特别是基于FULL INDEX SCAN 的时候,占用空间小的索引对内存占用也小很多。
PostgreSQL,SqlServer等都支持条件索引,所以我们先来看下条件索引的实际情况。
表结构如下,记录大概有10W行:
Table "ytt.girl1" Column | Type | Modifiers --------+---------+-------------------- id | integer | not null rank | integer | not null default 0 Indexes: "girl1_pkey" PRIMARY KEY, btree (id) "idx_girl1_rank" btree (rank) WHERE rank >= 10 AND rank Index Scan using idx_girl1_rank on girl1 (cost=0.29..421.26 rows=232 width=8) (actual time=0.023..0.044 rows=20 loops=1) Index Cond: ((rank >= 20) AND (rank Index Scan using idx_girl1_rank on girl1 (cost=0.28..513.44 rows=291 width=8) (actual time=0.033..0.061 rows=20 loops=1) Index Cond: ((rank >= 20) AND (rank
可以看出,在扫描的记录数以及时间上,条件索引的优势都很明显。
接下来,我们在MySQL 模拟下这样的过程。
由于MySQL 不支持这样的索引, 在SQL层面上,只能创建一个索引表来保存对应条件的主键以及索引键。ytt>show create table girl1_filtered_index; +----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | girl1_filtered_index | CREATE TABLE `girl1_filtered_index` ( `id` int(11) NOT NULL, `rank` int(11) NOT NULL DEFAULT '0', PRIMARY KEY (`id`), KEY `idx_rank` (`rank`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 | +----------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec) 接下来,对基础表的更新操作做下修改,创建了三个触发器。 DELIMITER $$ USE `t_girl`$$ DROP TRIGGER /*!50032 IF EXISTS */ `filtered_insert`$$ CREATE /*!50017 DEFINER = 'root'@'localhost' */ TRIGGER `filtered_insert` AFTER INSERT ON `girl1` FOR EACH ROW BEGIN IF new.rank BETWEEN 10 AND 100 THEN INSERT INTO girl1_filtered_index VALUES (new.id,new.rank); END IF; END; $$ DELIMITER ; DELIMITER $$ USE `t_girl`$$ DROP TRIGGER /*!50032 IF EXISTS */ `filtered_update`$$ CREATE /*!50017 DEFINER = 'root'@'localhost' */ TRIGGER `filtered_update` AFTER UPDATE ON `girl1` FOR EACH ROW BEGIN IF new.rank BETWEEN 10 AND 100 THEN REPLACE girl1_filtered_index VALUES (new.id,new.rank); ELSE DELETE FROM girl1_filtered_index WHERE id = old.id; END IF; END; $$ DELIMITER ; DELIMITER $$ USE `t_girl`$$ DROP TRIGGER /*!50032 IF EXISTS */ `filtered_delete`$$ CREATE /*!50017 DEFINER = 'root'@'localhost' */ TRIGGER `filtered_delete` AFTER DELETE ON `girl1` FOR EACH ROW BEGIN DELETE FROM girl1_filtered_index WHERE id = old.id; END; $$ DELIMITER ; OK,我们导入测试数据。 ytt>load data infile 'girl1.txt' into table girl1 fields terminated by ','; Query OK, 100000 rows affected (1.05 sec) Records: 100000 Deleted: 0 Skipped: 0 Warnings: 0 ytt>select count(*) from girl1; +----------+ | count(*) | +----------+ | 100000 | +----------+ 1 row in set (0.04 sec) ytt>select count(*) from girl1_filtered_index; +----------+ | count(*) | +----------+ | 640 | +----------+ 1 row in set (0.00 sec)
这里,我们把查询语句修改成基础表和条件索引表的JOIN。select a.id,a.rank from girl1 as a where a.id in (select b.id from girl1_filtered_index as b where b.rank between 20 and 60) limit 20;
当然这只是功能上的一个演示。 最终实现得靠MySQL 5.8了。^____^
推荐阅读
-
Mysql Data目录和 Binlog 目录 搬迁的方法
-
Windows下实现MySQL自动备份的批处理(复制目录或mysqldump备份)
-
Linux中更改转移mysql数据库目录的步骤
-
Mysql Data目录和 Binlog 目录 搬迁的方法
-
MySQL中使用case when 语句实现多条件查询的方法
-
Linux中更改转移mysql数据库目录的步骤
-
Windows 64 位 mysql 5.7以上版本包解压中没有data目录和my-default.ini及服务无法启动的快速解决办法(问题小结)
-
MySql 中聚合函数增加条件表达式的方法
-
mysql 5.7.21 解压版通过历史data目录恢复数据的教程图解
-
Python3连接MySQL(pymysql)模拟转账实现代码