1. 數據庫索引
1.1 索引作用
當我們在數據庫表中查詢數據時,若沒有索引,會逐個遍歷表格中的所有記錄,表格中數據記錄量大時很耗時。建立索引就像創建目錄一樣,直接通過索引找到數據存儲位置,加快查找。例如:有一張person表,其中有2W條記錄,記錄着2W個人的信息。有一個Phone的字段記錄每個人的電話號碼,現在想要查詢出電話號碼為xxxx的人的信息。
如果沒有索引,那么將從表中第一條記錄一條條往下遍歷,直到找到該條信息為止。
如果有了索引,那么會將該Phone字段,通過一定的方法進行存儲,好讓查詢該字段上的信息時,能夠快速找到對應的數據,而不必在遍歷2W條數據了。其中MySQL中的索引的存儲類型有兩種:BTREE、HASH。 也就是用樹或者Hash值來存儲該字段,要知道其中詳細是如何查找的,就需要會算法的知識了。
但索引也不是越多越好,因為創建的索引也需要占用空間,而且需要維護索引,因此沒必要為所有字段創建索引,對於經常需要查詢,或數據記錄很多的字段可以創建索引。
1.2 索引分類(index或key)
索引是在存儲引擎中實現的,也就是說不同的存儲引擎,會使用不同的索引
MyISAM和InnoDB存儲引擎:只支持BTREE索引, 也就是說默認使用BTREE,不能夠更換
MEMORY/HEAP存儲引擎:支持HASH和BTREE索引
索引我們分為四類來講 單列索引(普通索引,唯一索引,主鍵索引)、組合索引、全文索引、空間索引、
單列索引:一個索引只包含單個列,但一個表中可以有多個單列索引。
普通索引, INDEX:MySQL中基本索引類型,沒有什么限制,允許在定義索引的列中插入重復值和空值,純粹為了查詢數據更快一點。
唯一索引,UNIQUE :索引列中的值必須是唯一的,但是允許為空值,
主鍵索引, PRIMARY KEY:是一種特殊的唯一索引,不允許有空值。
組合索引: 在表中的多個字段組合上創建的索引,只有在查詢條件中使用了這些字段的左邊字段時,索引才會被使用,使用組合索引時遵循最左前綴集合。
全文索引 FULLTEXT :只有在MyISAM引擎上才能使用 (MySQL 5.6版本的InnoDB 開始支持全文索引),只能在CHAR,VARCHAR,TEXT類型字段上使用全文索引,介紹了要求,說說什么是全文索引,就是在一堆文字中,通過其中的某個關鍵字等,就能找到該字段所屬的記錄行.
空間索引 SPATIAL : 只有在MyISAM引擎上才能使用(MySQL 5.7版本的InnoDB 開始支持),空間索引是對空間數據類型(坐標,地理位置等)的字段建立的索引,MySQL中的空間數據類型有四種,GEOMETRY、POINT、LINESTRING、POLYGON。創建空間索引的列,必須將其聲明為NOT NULL
另外索引也可以分為聚集索引和非聚集索引:
聚集(clustered)索引:數據行的物理順序與列值(一般是主鍵的那一列)的邏輯順序相同,一個表中只能擁有一個聚集索引。(即主鍵索引)
非聚集索引(輔助索引):該索引中索引的邏輯順序與磁盤上行的物理存儲順序不同,一個表中可以擁有多個非聚集索引。(包括普通索引,唯一索引,全文索引等)
1.3 索引操作
1.3.1 創建索引(create index): (創建索引后,通過SHOW CREATE TABLE tbname;能查看)
下面命令給titles表中的title列增加索引 (索引名稱為idxtitle,未命名時默認為該字段名稱),有三種方式如下:
1,創建表格時指定:
CREATE TABLE titles(
title varchar(100),
publID INT,
INDEX idxtitle (title)
);
2,創建索引: CREATE INDEX idxtitle ON titles(title);
3,修改表設計,添加索引: ALTER TABLE titles ADD INDEX idxtitle (title);
1.3.2增加不同的索引:
ALTER TABLE tablename ADD PRIMARY KEY (indexcols..); 不要寫索引名稱
ALTER TABLE tablename ADD INDEX [indexname] (indexcols..);
ALTER TABLE tablename ADD UNIQUE [indexname] (indexcols..);
ALTER TABLE tablename ADD FULLTEXT [indexname] (indexcols..);
ALTER TABLE tablename ADD INDEX [indexname] (indexcols1,indexcols2); 為indexcols1,indexcols2兩列創建組合索引
1.3.3刪除索引:
ALTER TABLE tablename DROP PRIMARY KEY ;
ALTER TABLE tablename DROP INDEX [indexname] ;
DROP indexname ON table_name;
1.3.4查看索引:
SHOW INDEX FROM table_name;
SHOW CREATE TABLE table_name;
DESC table_name
1.3.5 索引創建示例:

1 普通索引:加速查找功能 創建表時定義索引 CREATE TABLE user( nid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) NOT NULL, age INT NOT NULL, email VARCHAR(64) NOT NULL, index n_index (name) )ENGINE=INNODB DEFAULT CHARSET=utf8; 創建表后添加索引 CREATE INDEX a_index ON user(age); 查看索引 SHOW INDEX FROM user; 刪除索引 DROP INDEX a_index ON user; 注意:對於創建索引時如果是BLOB 和 TEXT 類型,必須指定length。 create index ix_extra on in1(extra(32)); 2.唯一索引功能:加速查找和唯一約束(可以為null) CREATE TABLE user( nid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) NOT NULL, age INT NOT NULL, email VARCHAR(64) NOT NULL, UNIQUE n_index (name) )ENGINE=INNODB DEFAULT CHARSET=utf8; CREATE INDEX a_index ON user(age); SHOW INDEX FROM user; DROP INDEX a_index ON user; 3. 主鍵索引功能:加速查找和唯一約束(不可為null),特殊的唯一索引 -- CREATE TABLE user( -- nid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, -- name VARCHAR(32) NOT NULL, -- age INT NOT NULL, -- email VARCHAR(64) NOT NULL, -- )ENGINE=INNODB DEFAULT CHARSET=utf8; -- 方式二 CREATE TABLE user( nid INT NOT NULL AUTO_INCREMENT, name VARCHAR(32) NOT NULL, age INT NOT NULL, email VARCHAR(64) NOT NULL, PRIMARY key (nid) )ENGINE=INNODB DEFAULT CHARSET=utf8; -- 創建和刪除 ALTER TABLE user ADD PRIMARY KEY(name); ALTER TABLE user DROP PRIMARY KEY; ALTER TABLE user MODIFY nid INT,DROP PRIMARY KEY; 4.組合索引:組合索引是將n個列組合成一個索引 其應用場景為:頻繁的同時使用n列來進行查詢,如:where name = 'zack' and password = "2222222" CREATE INDEX com_index ON user(name,age); 組合索引有最左前綴性,對於上述組合索引,查詢時: 查詢: name and email -- 使用索引 name -- 使用索引 email -- 不使用索引 注意:對於同時搜索n個條件時,組合索引的性能好於多個單一索引合並。
1.4 索引性能測試:
先創建person表格,通過存儲過程插入5000條數據

--創建表 CREATE TABLE person(id INT, name VARCHAR(16)); --存儲過程 (創建函數,delimiter $$:修改終止符號為$$) delimiter $$ CREATE PROCEDURE autoinsert() BEGIN DECLARE i INT DEFAULT 1; WHILE(i<5000) DO INSERT INTO person VALUES(i,'zack'); SET i=i+1; END WHILE; END$$ delimiter ; --調用函數 CALL autoinsert();
無index時查詢:SELECT * FROM person WHERE id=4900;
添加index后查詢:
ALTER TABLE person ADD INDEX index_id (id);
SELECT * FROM person WHERE id=4900;
可以看出有索引時查詢時間變快。
1.5.索引覆蓋
索引覆蓋:建立索引后並不是所有的查詢都會通過索引表查詢,通過索引表的查詢稱為索引覆蓋。
常見的不會覆蓋索引的情況:(通過explain語句分析,可以判斷是否覆蓋索引,但只是作為參考)

CREATE TABLE user( nid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(32) NOT NULL, age INT NOT NULL, email VARCHAR(64) NOT NULL, index n_index(name) )ENGINE=INNODB DEFAULT CHARSET=utf8; show index from user; name列為普通索引,id列為主鍵索引 不會覆蓋索引的情況: 1.以%開頭的模糊查詢:like "%cn" select * from user where name like '%cn'; 2. 使用函數: select * from user where reverse(name) = 'zack'; 3.OR語句中有一列不是索引列 select * from user where id = 1 or email = '6734@qq.com'; 下列特殊情況: select * from user where id = 1 or email = '6734@qq.com' and name = 'zack' 4. 類型不一致 (下面name列是字符串類型,傳入條件時必須用引號引起來,不然不會走索引) select * from user where name = 999; 5. 使用了!= select * from user where name != 'zack'; 特別的:如果是主鍵,則還是會走索引 select * from user where id != 123; 6. 使用了>,< (有可能覆蓋索引,不同版本不一致) select * from user where name > 'zack'; 特別的:如果是主鍵或索引是整數類型,則還是會走索引 select * from user where id > 123; select * from user where age > 123; 7. ORDER BY 語句根據索引列排序,選擇的映射如果不是索引,則不走索引 select email from user order by name desc; 下面會走索引:select name from user order by name desc; 特別的:如果對主鍵排序,則還是走索引: select * from user order by id desc; 8.組合索引最左前綴原理 如果組合索引為:(name,email) name and email -- 使用索引 name -- 使用索引 email -- 不使用索引
1.6 索引數據結構
(參考:http://blog.codinglabs.org/articles/theory-of-mysql-index.html)
一般索引采用B+ Tree和B- Tree實現,MySQL的InnoDB和MyISAM都采用B+ Tree實現,但存儲細節上不一樣。
MyISAM存儲引擎:MyISAM索引文件和數據文件是分離的,索引文件僅保存數據記錄的地址(葉節點data域)。
主鍵索引(primary key):其結構如下,B+ Tree的葉子節點的key存放主鍵值,data存放主鍵值對應數據行的存儲地址,而非葉子節點key為主鍵值,不存儲data。查找時通過key從上往下找到葉子結點,如果key存在,拿到數據行存儲地址。
輔助索引(secondary key):上圖中col1為主鍵,在col2上建立一個輔助索引,其結構如下,可以發現其結構和主鍵索引沒有區別,葉子節點data存放的也是數據行地址(不同之處在於主索引要求key是唯一的,而輔助索引的key可以重復)
InnoDB存儲引擎:InnoDB的數據文件本身就是索引文件,葉節點data域保存了完整的數據記錄
主鍵索引:其結構如下,B+ Tree的葉子節點key存放主鍵值,data存放完整的數據記錄。非葉子節點key為主鍵值,不存儲data。查找時通過key從上往下找到葉子結點,如果key存在,直接拿到數據。
輔助索引:對於輔助索引的結構如下,與主鍵索引不同的是,葉節點的data存放存放主鍵索引的值,而不是地址,因此輔助索引進行檢索時需要檢索兩遍索引,首先檢索輔助索引獲得主鍵,然后用主鍵到主索引中檢索獲得記錄。
通過上述結構發現,InnoDB數據文件即包含主鍵索引,所以InnoDB要求表必須有主鍵,如果沒有顯式指定,則MySQL系統會自動選擇一個可以唯一標識數據記錄的列作為主鍵,如果不存在這種列,則MySQL自動為InnoDB表生成一個隱含字段作為主鍵。而且不建議使用過長的字段作為主鍵,因為所有輔助索引都引用主索引,過長的主索引會令輔助索引變得過大。另外,用非單調的字段作為主鍵在InnoDB中也不建議,因為InnoDB數據文件本身是一顆B+Tree,非單調的主鍵會造成在插入新記錄時數據文件為了維持B+Tree的特性而頻繁的分裂調整,十分低效,而使用自增字段作為主鍵則是一個很好的選擇。
2,mysql數據庫引擎
https://dev.mysql.com/doc/refman/5.7/en/storage-engines.html
數據庫存儲引擎,是mysql用來處理SQL語句的組件,對每一個數據表格,創建時都需要指定一個數據庫引擎,mysql會使用該引擎來處理這個表格的相應操作,因此對於不同引擎的表格,SQL語句的處理結果和性能會不同。另外,對於一個數據庫中的表格,每個表格都可以指定不同的數據庫引擎。通過命令SHOW ENGINES;能查看mysql支持的數據庫引擎。主要有InnoDB,MyISAM, Memory, CSV, Archve, Blackhole等,常用的就是InnoDB,MyISAM, Memory。其中通過Create table 命令默認設置的引擎為InnoDB。
2.1 設置數據表格引擎:
創建表格時指定:CREATE TABLE titles(id INT, name VARCHAR(16)) ENGINE = InnoDB;
創建后修改:ALTER TABLE titles ENGINE = InnoDB;
(SET default_storage_engine=NDBCLUSTER;
設置默認的引擎)
2.2 InnoDB特點
https://dev.mysql.com/doc/refman/5.7/en/innodb-introduction.html
InnoDB支持事務操作,即commit,rollback和crash-recovery;
InnoDB支持行級鎖,即可以給一行數據上鎖;
InnoDB支持外鍵關系約束;
2.3 MyISAM特點
https://dev.mysql.com/doc/refman/5.7/en/myisam-storage-engine.html
MyISAM 適合讀取操作較多的數據表,其讀取速度較快;
MyISAM支持表級鎖,可以給一張表上鎖;
MyISAM支持全文索引;
MyISAM 支持Gometry,Point等表示空間位置的數據類型;
2.3 Memory:僅存在於內存中,多用於臨時表格(hash index)
3.ODBC和JDBC
ODBC(open database connectivity): windows系統中數據庫系統的一個驅動,基於ODBC的軟件能夠通過ODBC驅動來操控數據庫中的數據。(如excel, access 能夠通過ODBC連接MySQL 數據庫,進行數據的增刪改查
JDBC (java database connectivity):unix和Linux系統上數據庫系統的驅動。
參考博客:https://www.cnblogs.com/whgk/p/6179612.html
http://www.cnblogs.com/yuanchenqi/articles/6357507.html
MyISAM和InnoDB的區別:https://segmentfault.com/a/1190000008227211
聚集索引與非聚集索引:https://www.cnblogs.com/s-b-b/p/8334593.html