BTREE索引與HASH索引
阿新 • • 發佈:2018-12-13
memory儲存引擎的表可以選擇使用BTREE索引或者HASH索引,分別有自己的適用範圍。
如果童鞋沒有文中提到的表,請看附註。
- hash索引的適用範圍及缺陷 1、只用於 = 或<=>操作符的等式比較。 2、優化器不能使用hash索引加速order by操作; 3、當~ mysql不能確定在兩個值之間大約多少行。若將一個myisam表改為hash索引的memory表時,會影響一些查詢的執行效率。 4、只能使用整個關鍵字搜尋一行。
- BTREE索引 適用於 >、<、>=、<=、between、!=或者<> ,或者 like ‘parent’(parent不以萬用字元開始)操作符。
- 執行sql簡單瞭解下兩種索引。
1、下面範圍查詢適合btree和hash索引:
select * from customers where age=1 or age in(26,2,3);
; 2、下面範圍查詢只適用於BTREE索引:select * from customers where age >20 and age<30;
select * from customers where name like 't%' or name between 'tom' and 'jerry';
eg:建立一個和city表完全相同的memory 儲存引擎的表city_memory:
CREATE TABLE `city_memory` ( `city_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT, `city` varchar(50) NOT NULL, `country_id` smallint(5) unsigned NOT NULL, `last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (`city_id`), KEY `idx_fk_country_id` (`country_id`), CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`) REFERENCES `country` (`country_id`) ON UPDATE CASCADE ) ENGINE=Memory DEFAULT CHARSET=utf8; insert into city_memory select * from city;
當對索引欄位進行範圍查詢的時候,只有BTREE 索引可以通過索引訪問:
explain select * from city where country_id>1 and country_id<101 \G ;
而hash索引實際上是全表掃描的:explain select * from city_memory where country_id>1 and country_id<101 \G ;
當使用memory表時,如果預設建立hash索引,則要注意sql語句的編寫,確保可以使用上索引,如果一定要使用範圍查詢,那麼在建立索引時,則應該選擇建立成BTREE索引。
附註:測試資料準備:
CREATE TABLE `customers` (
`id` int(10) NOT NULL,
`name` varchar(20) DEFAULT NULL,
`age` int(3) DEFAULT NULL,
`birthday` datetime DEFAULT NULL,
`married` smallint(1) DEFAULT NULL COMMENT '1 :0δ',
`photo` blob COMMENT 'Ƭʹƴ',
`remak` varchar(100) DEFAULT NULL COMMENT 'ע',
`ctime` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
`sex` char(1) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (1, 'xianzi', 26, NULL, 0, NULL, NULL, '2018-10-5 20:36:07', NULL);
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (2, 'yanhua', 2, NULL, 0, NULL, NULL, '2018-10-5 20:36:10', NULL);
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (3, 'haidao', 3, NULL, 0, NULL, NULL, '2018-10-5 20:36:13', NULL);
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (4, 'xiao_lang', 14, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (5, 'yaxian_baby', 2, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (6, 'tom', 1, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (7, 'jerry', 1, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (8, '1', 11, NULL, 0, NULL, NULL, NULL, NULL);
INSERT INTO `customers` (`id`, `name`, `age`, `birthday`, `married`, `photo`, `remak`, `ctime`, `sex`) VALUES (9, '2', 21, NULL, 0, NULL, NULL, NULL, NULL);
CREATE TABLE `city` (
`city_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,
`city` varchar(50) NOT NULL,
`country_id` smallint(5) unsigned NOT NULL,
`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`city_id`),
KEY `idx_fk_country_id` (`country_id`),
CONSTRAINT `fk_city_country` FOREIGN KEY (`country_id`) REFERENCES `country` (`country_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=223 DEFAULT CHARSET=utf8;