1、mysql索引(基礎與規則)
索引規則:
一、 MySQL建表,字段需設置爲非空,需設置字段默認值。
二、 MySQL建表,字段需NULL時,需設置字段默認值,默認值不爲NULL。
三、 MySQL建表,如果字段等價於外鍵,應在該字段加索引。
四、 MySQL建表,不同表之間的相同屬性值的字段,列類型,類型長度,是否非空,是否默認值,需保持一致,否則無法正確使用索引進行關聯對比。
五、 MySQL使用時,一條SQL語句只能使用一個表的一個索引。所有的字段類型都可以索引,多列索引的屬性最多15個。
六、 如果可以在多個索引中進行選擇,MySQL通常使用找到最少行的索引,索引唯一值最高的索引。
七、 建立索引index(part1,part2,part3),相當於建立了index(part1),index(part1,part2)和index(part1,part2,part3)三個索引。
八、 MySQL針對like語法必須如下格式才使用索引:SELECT * FROM t1 WHERE key_col LIKE 'ab%' ;
九、 SELECT COUNT(*) 語法在沒有where條件的語句中執行效率沒有SELECT COUNT(col_name)快,但是在有where條件的語句中執行效率要快。
十、 在where條件中多個and的條件中,必須都是一個多列索引的key_part屬性而且必須包含key_part1。各自單一索引的話,只使用遍歷最少行的那個索引。
十一、 在where條件中多個or的條件中,每一個條件,都必須是一個有效索引。
十二、 ORDER BY 後面的條件必須是同一索引的屬性,排序順序必須一致(比如都是升序或都是降序)。
十三、 所有GROUP BY列引用同一索引的屬性,並且索引必須是按順序保存其關鍵字的。
十四、 JOIN 索引,所有匹配ON和where的字段應建立合適的索引。
十五、 對智能的掃描全表使用FORCE INDEX告知MySQL,使用索引效率更高。
十六、 定期ANALYZE TABLE tbl_name爲掃描的表更新關鍵字分佈 。
十七、 定期使用慢日誌檢查語句,執行explain,分析可能改進的索引。
十八、 條件允許的話,設置較大的key_buffer_size和query_cache_size的值(全局參數),和sort_buffer_size的值(session變量,建議不要超過4M)。
首先分析項目的數據表,都會有什麼樣的操作,比如產品列表,會按照分類、品牌等做where,按照時間、價格等排序(order by),所以做索引,個人覺得應該是按照業務邏輯去做。
索引類型:
(1) 普通索引
最簡單的索引方式,沒有太多的約束,創建方式如下:
創建:create index indexname on tablename(column(length));如果是字符型的字段,要指定length
(建表時指定)create table tablename ([….],index [indexname] (column(length));
修改:alter tablename add index [indexname] on (column(length))
刪除:drop index indexname on tablename
(2) 唯一索引
和普通索引的區別就是列值要唯一,允許有空值。(組合索引那組合後的列值也必須唯一)
創建:create unique index indexname on tablename (column(length))
(健表時指定)create table ([….],unique [indexname] (column(length)))
修改:alter tablename add unique [indexname] on (column(length))
(3) 主鍵索引
主鍵索引就比較清晰了,大家經常用到,只需要記住兩個概念就行了,不能爲空,列值唯一。
當然了,還有就是一個表只能有一個主鍵。
(4) 全文索引
Mysql3.23開始支持全文索引,在項目中還真沒用過,都用了sphinx全文檢索了。所以在此不贅述了。
單列索引和組合索引
爲了描述這兩個概念,我們首先建一張測試表
Create table student(
Id int not null auto_increment primary key,
Name char(100) not null,
Age tinyint not null,
Score tinyint not null default 0
)engine=myisam default charset=gbk;
測試表名爲student,字段name是名字,age是年齡,score是成績。
現在有這麼一條查詢語句:select id from student where name=’arkulo’ and age=20 and score=90;
首先分析單列索引:
如果在name、age和score的每個字段上建立索引,那就會產生三個結果集,然後再取其交集,最後在得出查詢結果
組合索引:
Alter table student add index name_age_score on (name(10),age,score);
建立組合索引,其中name(10),只提取名稱的前部分,既能減少索引文件的體積,又能加快插入操作。
有了組合索引,就相當於有了如下三個索引:
(name,age,socre)
(name,age)
(name)
這也就是通常所說的“最左前綴”的概念,其實說簡單點就是要按照索引的順序進行排列
如果有了這個組合索引,那上面那條查詢語句一次即可命中
什麼時候用索引
首先mysql只對<,<=,=,>=,>,between,in,like使用索引,因此where和join(on)的時候就應該考慮到使用什麼樣的索引,而且要記住一條sql語句只能使用一個索引,比如有where和order by同時出現的時候,order by 即使用的是索引字段,他也不會走索引。
索引的弱點
(1) 加了索引之後,那insert、delete和update操作都要更新索引,會造成一些附加操作
(2) 索引是保存在物理文件(.MYI)裏的,所以如果在一張大表上創建索引,勢必會造成索引文件也比較大
2、MySQL優化之索引創建規則
表的主鍵、外鍵必須有索引;
數據量超過300的表應該有索引;
經常與其他表進行連接的表,在連接字段上應該建立索引;
經常出現在Where子句中的字段,特別是大表的字段,應該建立索引;
索引應該建在選擇性高的字段上;
索引應該建在小字段上,對於大的文本字段甚至超長字段,不要建索引;
複合索引的建立需要進行仔細分析;儘量考慮用單字段索引代替:
正確選擇複合索引中的主列字段,一般是選擇性較好的字段;
複合索引的幾個字段是否經常同時以AND方式出現在Where子句中?單字段查詢是否極少甚至沒有?如果是,則可以建立複合索引;否則考慮單字段索引;
如果複合索引中包含的字段經常單獨出現在Where子句中,則分解爲多個單字段索引;
如果複合索引所包含的字段超過3個,那麼仔細考慮其必要性,考慮減少複合的字段;
如果既有單字段索引,又有這幾個字段上的複合索引,一般可以刪除複合索引;
頻繁進行數據操作的表,不要建立太多的索引;
刪除無用的索引,避免對執行計劃造成負面影響;
以上是一些普遍的建立索引時的判斷依據。一言以蔽之,索引的建立必須慎重,對每個索引的必要性都應該經過仔細分析,要有建立的依據。因爲太多的索引 與不充分、不正確的索引對性能都毫無益處:在表上建立的每個索引都會增加存儲開銷,索引對於插入、刪除、更新操作也會增加處理上的開銷。另外,過多的複合 索引,在有單字段索引的情況下,一般都是沒有存在價值的;相反,還會降低數據增加刪除時的性能,特別是對頻繁更新的表來說,負面影響更大。