對於一個MySQL的初學者來講,數據庫的索引和優化可能並無太大的感受吧,由於咱們並無面對過大數據的搜索的工做,在小的數據中,因爲咱電腦速度仍是比較快的,因此也沒什麼感受。我剛剛學數據庫的時候,一直覺得數據庫是很智能的,咱們加入、刪除和查詢的時候都是用很優的算法進行,可是今天我學習了數據庫索引以後才發現,原來當咱們對一個表若是不是用主鍵進行查詢的時候,數據庫是進行逐行比對的方式進行搜索,這應該是最慢最無語的方法了,因此咱們須要建立合適的索引幫助咱們實現數據庫的查詢。 算法
首先,筆者也是個二逼孩子。。。開始學的時候,覺得有了primary key咱們就能很快的查詢了,也以爲索引應該是基於primary key的。這種腦殘的想法不會只有我一我的有吧,因此開頭咱們就先談下索引和primary key的區別吧。 咱們須要知道主鍵是索引,但索引不必定是主鍵。而且主鍵具備惟一性,而只有惟一性索引才具備惟一性,主鍵的值不能爲空,不能重複,可是索引能夠在咱們程序中動態建立刪除。在做用方面:索引只是加快查詢和排序等操做的速度,可是primary key則是用於保證數據的完整性,同時也避免編寫一些觸發器。 sql
好了,下面進入正題哈: 數據庫
首先,咱們須要知道索引是什麼,索引是一種特殊的文件,它們包含着對數據表裏全部記錄的引用指針。就比如咱們的數據是一本書,而索引是書的目錄,在沒有索引的狀況下,咱們在查找內容時須要逐頁、逐行得進行搜索、比對,可是,在有了索引後,咱們就能夠直達咱們須要的內容。 學習
索引分爲聚簇索引和非聚簇索引兩種,聚簇索引是按照數據存放的物理位置爲順序的,而非聚簇索引就不同了;聚簇索引能提升多行檢索的速度,而非聚簇索引對於單行的檢索很快。 在這裏,筆者就在思考一個問題了,聚簇索引是要求文件的存放是有序的,而非聚簇索引則是無序的,這樣的話,在使用索引時咱們就有很大的限制了,那麼咱們應該怎樣解決這個問題呢,有待討論哈。 索引是能夠動態生成的,在咱們程序時候的時候生成一個須要的索引,在不須要的時候則進行刪除,可是,當咱們數據規模很大的時候,生成索引是一個極消耗資源的事情,可是呢,索引又是很龐大的,很佔用空間,因此咱們須要找到運算效率和存儲空間的一個平衡點。合理利用索引才能提升查詢效率,若是將不少時間用在建立索引上就很是不值得了。 大數據
這裏咱們使用的MySQL,在MySQL中的索引使用的都是B-TREE,這應該是最平衡的一種結構了,固然有的使用的HASH索引,應該說各有利弊,你們能夠查一下實現的方式學習一下,也有助於本身在從此在想要實現不一樣功能的時候靈活選擇索引的種類。優化
索引也是有很大壞處的,因爲須要大大提升查詢的速度,因此須要建立大量的指針和表,在進行INSERT、UPDATE、DELETE等修改操做時,因爲索引的存在,在更新數據的同時,也須要更新索引的文件,因此,濫用索引反而會大大下降數據庫的效率。 上面已經說過了,索引分爲聚簇索引和非聚簇兩類,那麼,對索引類型的選擇也就是一個問題。 聚簇索引和非聚簇索引的區別google看一看哈! 網站
選擇標準能夠參考下表(網上找的):google
下面,粗略介紹下索引的類型和使用吧,詳細的你們能夠看MySQL的document,可是比較繁瑣難懂就是了。spa
1. 普通索引指針
這是最基本的索引,它沒有任何限制,咱們應該不多用到,可是仍是要熟練掌握的。
–直接建立索引
CREATE INDEX indexName ON tableName(columnName)
–修改表結構的方式添加索引
ALTER TABLE tabelName ADD INDEX indexName(columnName)
–建立表的時候同時建立索引
CREATE TABLE tableName (
INDEX indexName (title(length))
)
2. 惟一索引
primary key 就是一個惟一索引,與普通索引相似,不一樣的就是:索引列的值必須惟一,但容許有空。若是是組合索引,則列值的組合必須惟一。
–建立惟一索引
CREATE UNIQUE INDEX indexName ON tableName(column)
–修改表結構
ALTER TABLE tableName ADD UNIQUE indexName (columnName)
–建立表的時候直接指定
CREATE TABLE tableName (
UNIQUE indexName (title(length))
);
3. 全文索引(FULLTEXT)
MySQL從3.23.23版開始支持全文索引和全文檢索,FULLTEXT索引僅可用於 MyISAM 表;他們能夠從CHAR、VARCHAR或TEXT列中做爲CREATE TABLE語句的一部分被建立,或是隨後使用ALTER TABLE 或CREATE INDEX被添加。
對於較大的數據集,將你的資料輸入一個沒有FULLTEXT索引的表中,而後建立索引,其速度比把資料輸入現有FULLTEXT索引的速度更爲快。固然了,因爲全文索引的特殊性,當數據量很大的時候,咱們進行全文索引的建立極度消耗運算資源,因此不建議在程序中動態得建立和刪除。同時,建議若是使用全文搜索,應該在建表的時候就進行創建索引。
–建立表的適合添加全文索引
CREATE TABLE tableName (
FULLTEXT (content)
);
–修改表結構添加全文索引
ALTER TABLE article ADD FULLTEXT index_content(content)
–直接建立索引
CREATE FULLTEXT INDEX index_content ON article(content)
4. 單列索引、多列索引
多個單列索引與單個多列索引的查詢效果不一樣,由於執行查詢時,MySQL只能使用一個索引,會從多個索引中選擇一個限制最爲嚴格的索引。對於新學者和小網站來講,多列索引應該是最多用的,也是最容易掌握的索引方式。
你們能夠搜一下,有許多大牛都進行了驗證,多列搜索是整體優於單列搜索的,這裏就不進行證實了。
5. 組合索引(最左前綴)
平時用的SQL查詢語句通常都有比較多的限制條件,因此爲了進一步榨取MySQL的效率,就要考慮創建組合索引。例如一個組合索引:ALTER TABLE tableName ADD INDEX indexName(a(50),b(10))。創建這樣的組合索引,實際上是至關於分別創建了下面兩組組合索引:
–a,b
–a
說一點點學習心得:學習SQL是一個很是煩索的過程,咱們不該該僅僅侷限於會使用,善於使用。正所謂磨刀不誤砍柴功,在學習過程當中應該注重一下基礎的數學理論,不要急於作項目、作工程。
附上剛剛寫的DB做業的數據庫代碼吧。。。好渣渣,給新學者們一個參考:
CREATE DATABASE IF NOT EXISTS DBJob character set UTF8; USE DBJob; CREATE TABLE student( sid VARCHAR(45) NOT NULL, name VARCHAR(45) NOT NULL, university VARCHAR(45) NOT NULL, email VARCHAR(45) NULL, phone VARCHAR(45) NOT NULL, password VARCHAR(45) NOT NULL, PRIMARY KEY (sid)); alter table student add index FIND_BY_NAME(name); alter table student add index MULTI_FIND_S(sid,name); CREATE TABLE enterprise( eid VARCHAR(45) NOT NULL, ename VARCHAR(45) NOT NULL, phone VARCHAR(45) NOT NULL, email VARCHAR(45) NULL, password VARCHAR(45) NOT NULL, detail_information VARCHAR(200) NULL, PRIMARY KEY (eid)); alter table enterprise add index FIND_BY_ENAME(ename); alter table enterprise add index MULTI_FIND_E(eid,ename); CREATE TABLE job( jid INT NOT NULL, eid VARCHAR(45) NOT NULL, workplace VARCHAR(45) NULL, category VARCHAR(45) NULL, start_time DATETIME NOT NULL, end_time DATETIME NOT NULL, payment VARCHAR(45) NULL, paytype char(1) NULL, rec_num INT NULL, detail VARCHAR(45) NULL, PRIMARY KEY (jid,eid), CONSTRAINT eid FOREIGN KEY (eid) REFERENCES enterprise (eid) ON DELETE NO ACTION ON UPDATE NO ACTION); alter table job add index FIND_BY_EID(eid); alter table job add index FIND_BY_PAY(payment); alter table job add index FIND_BY_TIME(start_time,end_time); CREATE TABLE job_wanted( sid VARCHAR(45) NOT NULL, jid INT NOT NULL, PRIMARY KEY (jid, sid), FOREIGN KEY (sid) REFERENCES student (sid), FOREIGN KEY (jid) REFERENCES job (jid) ON DELETE NO action ON UPDATE NO action);