1. 程式人生 > >BTREE索引與HASH索引

BTREE索引與HASH索引

      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;