多列索引和多個單列索引
參考文章:
http://blog.csdn.net/wulex/article/details/69540136
http://blog.csdn.net/gol_phing/article/details/47100619
在關係資料庫中,索引是一種單獨的、物理的對資料庫表中一列或多列的值進行排序的一種儲存結構
1,建立索引
對於查詢佔主要的應用來說,索引顯得尤為重要。很多時候效能問題很簡單的就是因為我們忘了新增索引而造成的,或者說沒有新增更為有效的索引導致。如果不加索引的話,那麼查詢任何哪怕只是一條特定的資料都會進行一次全表掃描,如果一張表的資料量很大而符合條件的結果又很少,那麼不加索引會引起致命的效能下降。但是也不是什麼情況都非得建索引不可,比如性別可能就只有兩個值,建索引不僅沒什麼優勢,還會影響到更新速度,這被稱為過度索引。
2,複合索引
比如有一條語句是這樣的:select * from users where area=’beijing’ and age=22;
如果我們是在area和age上分別建立單個索引的話,由於mysql查詢每次只能使用一個索引,所以雖然這樣已經相對不做索引時全表掃描提高了很多效
率,但是如果在area、age兩列上建立複合索引的話將帶來更高的效率。如果我們建立了(area, age,
salary)的複合索引,那麼其實相當於建立了(area,age,salary)、(area,age)、(area)三個索引,這被稱為最佳左字首
特性
3,索引不會包含有NULL值的列
只要列中包含有NULL值都將不會被包含在索引中,複合索引中只要有一列含有NULL值,那麼這一列對於此複合索引就是無效的。所以我們在資料庫設計時不要讓欄位的預設值為NULL。
4,使用短索引
對串列進行索引,如果可能應該指定一個字首長度。例如,如果有一個CHAR(255)的 列,如果在前10 個或20 個字元內,多數值是惟一的,那麼就不要對整個列進行索引。短索引不僅可以提高查詢速度而且可以節省磁碟空間和I/O操作。
5,排序的索引問題
mysql查詢只使用一個索引,因此如果where子句中已經使用了索引的話,那麼order by中的列是不會使用索引的。因此資料庫預設排序可以符合要求的情況下不要使用排序操作;儘量不要包含多個列的排序,如果需要最好給這些列建立複合索引。
6,like語句操作
一般情況下不鼓勵使用like操作,如果非使用不可,如何使用也是一個問題。like “%a%” 不會使用索引而like “aaa%”可以使用索引。
7,不要在列上進行運算
select * from users where
YEAR(adddate)
8,不使用NOT IN和操作
NOT IN和操作都不會使用索引將進行全表掃描。NOT IN可以NOT EXISTS代替,id3則可使用id>3 or id
多列索引和多個單列索引
對於要經常查詢的含量大量資料的資料庫,建立索引是非常重要的,建立索引一般都是在where語句用得較多的列上。現在有個問題,如果一個表有多個列需要建立索引,是把所有列建成一個索引,還是對每一個列建一個索引,上篇文章做了一個介紹,這是作者得出的結論,Conclusion: For benchmarked queries we can see Multiple Column index beats Index Merge in all cases when such index can be used. It is also worth to watchout a MySQL may decide not to do Index merge (either intersection or union) but instead do full table scan or access table picking only one index on the pair.意思應該是說對多個列建索引比對每個列分別建索引更有優勢,而且要知道索引建立得越多就越佔磁碟空間,在更新資料的時候速度會更慢。
另外一篇文章How to create a successful multi-column index 則介紹瞭如何去建立一個多列索引,最重要的一個問題是如何安排列的順序是至關重要的,比如需要對一個表裡面的兩個欄位foo,bar建一個索引,那麼索引的順序是(foo,bar)還是(bar,foo)呢。在搞清楚如何安排順序之前先了解一個概念,cardinality:金山的翻譯是"集的勢",比如,tb表有1700條記錄,foo欄位有750個不同的記錄,那麼就可以說We have a cardinality of 750 for foo。總規則可以說是cardinality越大的欄位應該排在索引的第一位就是說索引的位置是(foo,bar),因為cardinality越大那麼第一次取出來的記錄集就越小,再進行第二次查詢的次數就越少了。不過這只是對於建兩個索引的規則,如果是三個以上就沒有那麼簡單了,具體地看原文,有比較詳細的例子。還需要提出的是即使我們建了一個很有效的索引,但是查詢優化器也許會選擇不用它,如果它會考慮更多因素以決定這個索引是否有足夠的效率。It was also pointed out to me, that even if an efficient multi-column index is created, the query optimizer may choose to never use it. This is because the optimizer looks at further statistics to determine if the index would be efficient enough or not.
Mysql資料庫提供兩種型別的索引,如果沒正確設定,索引的利用效率會大打折扣卻完全不知問題出在這。
CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (last_name,first_name)
);
以上建立的其實是一個多列索引,建立列索引的程式碼如下:
[c-sharp] view plaincopy
CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (last_name),
INDEX_2 name (first_name)
);
一個多列索引可以認為是包含通過合併(concatenate)索引列值建立的值的一個排序陣列。 當查詢語句的條件中包含last_name 和 first_name時,例如:
[c-sharp] view plaincopy
1. SELECT * FROM test WHERE last_name='Kun' AND first_name='Li';
sql會先過濾出last_name符合條件的記錄,在其基礎上在過濾first_name符合條件的記錄。那如果我們分別在last_name和first_name上建立兩個列索引,mysql的處理方式就不一樣了,它會選擇一個最嚴格的索引來進行檢索,可以理解為檢索能力最強的那個索引來檢索,另外一個利用不上了,這樣效果就不如多列索引了。
但是多列索引的利用也是需要條件的,以下形式的查詢語句能夠利用上多列索引:
[c-sharp] view plaincopy
1. SELECT * FROM test WHERE last_name='Widenius';
2.
3. SELECT * FROM test WHERE last_name='Widenius' AND first_name='Michael';
4.
5. SELECT * FROM test WHERE last_name='Widenius' AND (first_name='Michael' OR first_name='Monty');
6.
7. SELECT * FROM test WHERE last_name='Widenius' AND first_name >='M' AND first_name < 'N';
以下形式的查詢語句利用不上多列索引:
[c-sharp] view plaincopy
1. SELECT * FROM test WHERE first_name='Michael';
2.
3. SELECT * FROM test WHERE last_name='Widenius' OR first_name='Michael';
多列建索引比對每個列分別建索引更有優勢,因為索引建立得越多就越佔磁碟空間,在更新資料的時候速度會更慢。
另外建立多列索引時,順序也是需要注意的,應該將嚴格的索引放在前面,這樣篩選的力度會更大,效率更高。
對於要經常查詢的含量大量資料的資料庫,建立索引是非常重要的,建立索引一般都是在where語句用得較多的列上。現在有個問題,如果一個表有多個列需要建立索引,是把所有列建成一個索引,還是對每一個列建一個索引,上篇文章做了一個介紹,這是作者得出的結論,Conclusion: For benchmarked queries we can see Multiple Column index beats Index Merge in all cases when such index can be used. It is also worth to watchout a MySQL may decide not to do Index merge (either intersection or union) but instead do full table scan or access table picking only one index on the pair.意思應該是說對多個列建索引比對每個列分別建索引更有優勢,而且要知道索引建立得越多就越佔磁碟空間,在更新資料的時候速度會更慢。
另外一篇文章How to create a successful multi-column index 則介紹瞭如何去建立一個多列索引,最重要的一個問題是如何安排列的順序是至關重要的,比如需要對一個表裡面的兩個欄位foo,bar建一個索引,那麼索引的順序是(foo,bar)還是(bar,foo)呢。在搞清楚如何安排順序之前先了解一個概念,cardinality:金山的翻譯是"集的勢",比如,tb表有1700條記錄,foo欄位有750個不同的記錄,那麼就可以說We have a cardinality of 750 for foo。總規則可以說是cardinality越大的欄位應該排在索引的第一位就是說索引的位置是(foo,bar),因為cardinality越大那麼第一次取出來的記錄集就越小,再進行第二次查詢的次數就越少了。不過這只是對於建兩個索引的規則,如果是三個以上就沒有那麼簡單了,具體地看原文,有比較詳細的例子。還需要提出的是即使我們建了一個很有效的索引,但是查詢優化器也許會選擇不用它,如果它會考慮更多因素以決定這個索引是否有足夠的效率。It was also pointed out to me, that even if an efficient multi-column index is created, the query optimizer may choose to never use it. This is because the optimizer looks at further statistics to determine if the index would be efficient enough or not.
Mysql資料庫提供兩種型別的索引,如果沒正確設定,索引的利用效率會大打折扣卻完全不知問題出在這。
CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (last_name,first_name)
);
以上建立的其實是一個多列索引,建立列索引的程式碼如下:
[c-sharp] view plaincopy
CREATE TABLE test (
id INT NOT NULL,
last_name CHAR(30) NOT NULL,
first_name CHAR(30) NOT NULL,
PRIMARY KEY (id),
INDEX name (last_name),
INDEX_2 name (first_name)
);
一個多列索引可以認為是包含通過合併(concatenate)索引列值建立的值的一個排序陣列。 當查詢語句的條件中包含last_name 和 first_name時,例如:
[c-sharp] view plaincopy
1. SELECT * FROM test WHERE last_name='Kun' AND first_name='Li';
sql會先過濾出last_name符合條件的記錄,在其基礎上在過濾first_name符合條件的記錄。那如果我們分別在last_name和first_name上建立兩個列索引,mysql的處理方式就不一樣了,它會選擇一個最嚴格的索引來進行檢索,可以理解為檢索能力最強的那個索引來檢索,另外一個利用不上了,這樣效果就不如多列索引了。
但是多列索引的利用也是需要條件的,以下形式的查詢語句能夠利用上多列索引:
[c-sharp] view plaincopy
1. SELECT * FROM test WHERE last_name='Widenius';
2.
3. SELECT * FROM test WHERE last_name='Widenius' AND first_name='Michael';
4.
5. SELECT * FROM test WHERE last_name='Widenius' AND (first_name='Michael' OR first_name='Monty');
6.
7. SELECT * FROM test WHERE last_name='Widenius' AND first_name >='M' AND first_name < 'N';
以下形式的查詢語句利用不上多列索引:
[c-sharp] view plaincopy
1. SELECT * FROM test WHERE first_name='Michael';
2.
3. SELECT * FROM test WHERE last_name='Widenius' OR first_name='Michael';
多列建索引比對每個列分別建索引更有優勢,因為索引建立得越多就越佔磁碟空間,在更新資料的時候速度會更慢。
另外建立多列索引時,順序也是需要注意的,應該將嚴格的索引放在前面,這樣篩選的力度會更大,效率更高。