索引
是用來快速檢索出具備特定值的記錄。若是沒有索引,數據庫就必須從第一條記錄開始進行全表掃描,直到找出相關的行。數據越多,檢索的代價就越高,檢索時若是表的列存在索引,那麼MySQL
就能快速到達指定位置去搜索數據文件,而沒必要查看全部數據。
<!-- more -->java
索引依託於存儲引擎的實現,所以,每種存儲引擎的索引都不必定徹底相同,而且每種存儲引擎也不必定支持全部索引類型。全部存儲引擎支持每一個表至少16個索引,總索引長度至少爲256字節。大多數存儲引擎有更高的額限制。mysql
MySQL中索引的存儲類型有兩種:BTREE和HASH
,具體和表的存儲引擎相關;sql
MyISAM和InnoDB存儲引擎只支持BTREE索引,MEMORY/HEAP存儲引擎能夠支持HASH和BTREE索引。數據庫
優勢
缺點
普通索引和惟一索引
單列索引和組合索引
全文索引
FULLTEXT
,在定義索引的列上支持值的全文查找,容許在這些索引列中插入重複值和空值。全文索引能夠在CHAR、VARCHAR或者TEXT類型的列上建立,MySQL中只有MyISAM存儲引擎支持全文索引 索引設計不合理或者缺乏索引都會對數據庫和應用程序的性能形成障礙,高效的索引對於得到良好的性能很是重要。微信
注意事項
INSERT、DELETE、UPDATE
等語句的性能,由於當表中的數據更改的同時,索引也會進行調整和更新使用 CREATE TABLE 建立表的時候,除了能夠定義列的數據類型,還能夠定義主鍵約束、外鍵約束或者惟一性約束,而不論建立哪一種約束,在定義約束的同時至關於在指定列上建立了一個索引。架構
建立表時建立索引的基本語法以下:
CREATE TABLE table_name[col_name data_type] [UNIQUE|FULLTEXT|SPATIAL] [INDEX|KEY] [index_name](col_name[length]) [ASC|DESC]
釋義
-- 這句做用是,若是 customer1 存在就刪除 DROP TABLE IF EXISTS customer1; CREATE TABLE `customer1` ( `customer_id` bigint(20) NOT NULL COMMENT '客戶ID', `customer_name` varchar(30) DEFAULT NULL COMMENT '客戶姓名', INDEX `idx_customer_id` (`customer_id`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='客戶表';
測試
-- 查看當前表的索引狀況 SHOW INDEX FROM customer1; -- 使用 EXPLAIN 分析 SQL語句 是否使用了索引 EXPLAIN SELECT * FROM customer1 WHERE customer_id = 1;
釋義
EXPLAIN 語法下章會詳細講解,本章重心是索引性能
MySQL
執行查詢時預計從當前數據表中讀出的數據行數SHOW INDEX FROM 語法測試
當 possible_keys
與 key
都爲 idx_customer_id
,說明查詢時使用了索引優化
單列索引是在數據表中的某一個字段上建立的索引,一個表中能夠建立多個單列索引,前面兩個例子中建立的索引都是單列索引,好比:spa
DROP TABLE IF EXISTS customer1; CREATE TABLE `customer1` ( `customer_id` BIGINT (20) NOT NULL COMMENT '客戶ID', `customer_name` VARCHAR (30) DEFAULT NULL COMMENT '客戶姓名', UNIQUE INDEX `idx_customer_id` (`customer_id`) USING BTREE ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = '客戶表';
這樣就表明在表的customer_id
字段上建立了一個名爲idx_customer_id
的惟一索引
組合索引是在多個字段上建立一個索引,好比:
DROP TABLE IF EXISTS customer1; CREATE TABLE `customer1` ( `customer_id` BIGINT (20) NOT NULL COMMENT '客戶ID', `customer_name` VARCHAR (30) DEFAULT NULL COMMENT '客戶姓名', INDEX `idx_group_customer` (`customer_id`,`customer_name`) USING BTREE ) ENGINE = INNODB DEFAULT CHARSET = utf8mb4 COMMENT = '客戶表'; SHOW INDEX FROM customer1;
這就爲customer_id、customer_name
兩個字段成功建立了一個名爲idx_group_customer
的組合索引,經過SHOW INDEX FROM customer1;
將會看到兩條記錄(附圖)
全文索引能夠對全文進行搜索,只有MyISAM存儲引擎支持全文索引,而且只爲CHAR、VARCHAR和TEXT列,索引老是對整個列進行,不支持局部索引,好比:
DROP TABLE IF EXISTS customer1; CREATE TABLE `customer1` ( `customer_id` BIGINT (20) NOT NULL COMMENT '客戶ID', `customer_name` VARCHAR (255) DEFAULT NULL COMMENT '客戶姓名', FULLTEXT INDEX `idx_fulltext_customer_name` (`customer_name`) ) ENGINE = MyISAM DEFAULT CHARSET = utf8mb4 COMMENT = '客戶表'; SHOW INDEX FROM customer1;
由於默認的存儲引擎爲InnoDB
,而全文索引只支持MyISAM
,因此這裏建立表的時候要手動指定一下引擎。
看到這麼建立,就在info字段上成功創建了一個名爲idx_fulltext_customer_name
的FULLTEXT全文索引,全文索引很是適合大型數據庫,而對於小的數據集,它的用處可能比較小
在已經存在的表上建立索引,可使用ALTER TABLE語句或者CREATE INDEX語句,因此,分別講解一下如何使用ALTER TABLE和CREATE INDEX語句在已知的表字段上建立索引。
ALTER TABLE建立索引的基本語法爲:
ALTER TABLE table_name ADD [UNIQUE|FUUTEXT|SPATIAL] [INDEX|KEY] [index_name] (col_name[length],...) [ASC|DESC]
普通索引
ALTER TABLE customer1 ADD INDEX idx_customer_id(`customer_id`); ALTER TABLE customer1 ADD INDEX idx_customer_id(customer_name(50));
意思是查詢的時候,只須要檢索前面50個字符。這裏專門提一下,對字符串類型的字段進行索引,若是能夠儘量的指定一個前綴長度,例如,一個CHAR(255)的列,若是在前10個或者前30個字符內,多數值是惟一的,則不須要對整個列進行索引,短索引不只能夠提升查詢速度並且能夠節省磁盤空間、減小I/O操做。
惟一索引
ALTER TABLE customer1 ADD UNIQUE INDEX `idx_customer_id` (`customer_id`);
組合索引
ALTER TABLE customer1 ADD INDEX `idx_group_customer` (`customer_id`,`customer_name`);
CREATE INDEX語句能夠在已經存在的表上添加索引,MySQL中CREATE INDEX被映射到一個ALTER TABLE語句上,基本語法結構爲:
CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name ON table_name(col_name[length],...)[ASC|DESC]
看到和ALTER INDEX語句的語法基本同樣,下面把 customer1
表刪除了再建立,全部字段都沒有索引,用CREATE INDEX語句建立一次索引:
CREATE INDEX idx_customer_id ON customer1(`customer_id`); CREATE UNIQUE INDEX idx_customer_id ON customer1(`customer_id`); CREATE INDEX idx_group_customer ON customer1(`customer_id`,`customer_name`);
最後一項工做就是刪除索引了,可使用ALTER TABLE和DROP INDEX
刪除索引。
ALTER TABLE的基本語法爲:
ALTER TABLE table_name DROP EXISTS index_name; ALTER TABLE table_name DROP INDEX IF EXISTS index_name;
建議你們使用第二條
DROP INDEX的基本語法爲:
DROP INDEX index_name ON table_name DROP INDEX IF EXISTS index_name ON table_name
建議你們使用第二條
注意一個細節,刪除表中的列時,若是要刪除的列爲整個索引的組成部分,則該列也會從索引中刪除;若是組成索引的全部列都被刪除,則整個索引將被刪除
關注微信公衆號:battcn
後臺回覆 mysql
便可得到 《打造扛得住的MySQL數據庫架構》