-
1 # Java實戰技術
-
2 # 會點程式碼的大叔
透過最佳化SQL語句,提高資料庫查詢效率,我總結了有這麼幾個方面:
減少資料訪問看起來像一句廢話,少訪問資料當然可以提高速度了,減少資料訪問有這麼幾個方法:
建立並正確使用索引
我們經常用到的就是B-TREE索引,我們經常說到的【索引】也指的是【B-TREE索引】。
正確使用索引可以讓查詢效率翻倍,但是如果使用不正確,也會對效率降低很多,比如這幾種情況就會造成索引失效:
不等於操作:<>? 、not in("")
進行了運算後的欄位:column+1(簡單的運算),function(column)(函式)
含前導模糊查詢:like "%xxx"
IS NULL
隱式型別轉換:column是char型別,但是寫成column = 123(右邊是另外一種型別)
只通過索引訪問資料有些時候,我們只需要訪問表中的某幾個列的資料,我們可以為這幾個欄位建立一個組合索引,這樣的話只通過索引就可以得到資料,可以較小IO的開銷。比如:
select name,gender from users where age="25";
如果這個SQL用的頻率很高,那麼我們可以建立一個組合索引:
create index index_xxx on users(name,gender,age);
在執行這個sql的時候,資料全部都是透過索引找到的,都不需要訪問users表。
最佳化SQL執行計劃執行計劃表示SQL在執行時候的演算法,有的時候SQL語句很複雜,就需要最佳化SQL的執行計劃去提高SQL的執行效率。
其他可能不和SQL有直接的關係,但確實效率提升很明顯,比如:
資料分頁處理只返回需要的欄位減少互動次數(batch DML)使用繫結變數(可以減少資料庫伺服器CPU運算)但是要注意,對SQL不要過度最佳化,滿足需求即可。
-
3 # 電腦學堂
mysql的效能最佳化包羅甚廣: 索引最佳化,查詢最佳化,查詢快取,伺服器設定最佳化,作業系統和硬體最佳化,應用層面最佳化(web伺服器,快取)等等。這裡的記錄的最佳化技巧更適用於開發人員,都是從網路上收集和自己整理的,主要是查詢語句上面的最佳化,其它層面的最佳化技巧在此不做記錄。
查詢的開銷指標:
執行時間 檢查的行數 返回的行數
建立索引的幾個準則:
1、合理的建立索引能夠加速資料讀取效率,不合理的建立索引反而會拖慢資料庫的響應速度。
2、索引越多,更新資料的速度越慢。
3、儘量在採用MyIsam作為引擎的時候使用索引(因為MySQL以BTree儲存索引),而不是InnoDB。但MyISAM不支援Transcation。
4、當你的程式和資料庫結構/SQL語句已經最佳化到無法最佳化的程度,而程式瓶頸並不能順利解決,那就是應該考慮使用諸如memcached這樣的分散式快取系統的時候了。 5、習慣和強迫自己用EXPLAIN來分析你SQL語句的效能。
1. count的最佳化
比如:計算id大於5的城市 a. select count(*) from world.city where id > 5; b. select (select count(*) from world.city) – count(*) from world.city where id <= 5; a語句當行數超過11行的時候需要掃描的行數比b語句要多, b語句掃描了6行,此種情況下,b語句比a語句更有效率。當沒有where語句的時候直接select count(*) from world.city這樣會更快,因為mysql總是知道表的行數。
2. 避免使用不相容的資料型別。
例如float和int、char和varchar、binary和varbinary是不相容的。資料型別的不相容可能使最佳化器無法執行一些本來可以進行的最佳化操作。 在程式中,保證在實現功能的基礎上,儘量減少對資料庫的訪問次數;透過搜尋引數,儘量減少對錶的訪問行數,最小化結果集,從而減輕網路負擔;能夠分開的操作儘量分開處理,提高每次的響應速度;在資料視窗使用SQL時,儘量把使用的索引放在選擇的首列;演算法的結構儘量簡單;在查詢時,不要過多地使用萬用字元如 SELECT * FROM T1語句,要用到幾列就選擇幾列如:SELECT COL1,COL2 FROM T1;在可能的情況下儘量限制儘量結果集行數如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因為某些情況下使用者是不需要那麼多的資料的。不要在應用中使用資料庫遊標,遊標是非常有用的工具,但比使用常規的、面向集的SQL語句需要更大的開銷;按照特定順序提取資料的查詢。
3. 索引欄位上進行運算會使索引失效。
儘量避免在WHERE子句中對欄位進行函式或表示式操作,這將導致引擎放棄使用索引而進行全表掃描。如: SELECT * FROM T1 WHERE F1/2=100 應改為: SELECT * FROM T1 WHERE F1=100*2
4. 避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等這樣的運算子.
因為這會使系統無法使用索引,而只能直接搜尋表中的資料。例如: SELECT id FROM employee WHERE id != “B%” 最佳化器將無法透過索引來確定將要命中的行數,因此需要搜尋該表的所有行。在in語句中能用exists語句代替的就用exists.
5. 儘量使用數字型欄位.
一部分開發人員和資料庫管理人員喜歡把包含數值資訊的欄位 設計為字元型,這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎在處理查詢和連接回逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。
6. 合理使用EXISTS,NOT EXISTS子句。如下所示:
1.SELECT SUM(T1.C1) FROM T1 WHERE (SELECT COUNT(*)FROM T2 WHERE T2.C2=T1.C2>0) 2.SELECT SUM(T1.C1) FROM T1WHERE EXISTS(SELECT * FROM T2 WHERE T2.C2=T1.C2) 兩者產生相同的結果,但是後者的效率顯然要高於前者。因為後者不會產生大量鎖定的表掃描或是索引掃描。如果你想校驗表裡是否存在某條紀錄,不要用count(*)那樣效率很低,而且浪費伺服器資源。可以用EXISTS代替。如: IF (SELECT COUNT(*) FROM table_name WHERE column_name = ‘xxx’)可以寫成:IF EXISTS (SELECT * FROM table_name WHERE column_name = ‘xxx’)
7. 能夠用BETWEEN的就不要用IN
8. 能夠用DISTINCT的就不用GROUP BY
9. 儘量不要用SELECT INTO語句。SELECT INTO 語句會導致表鎖定,阻止其他使用者訪問該表。
10. 必要時強制查詢最佳化器使用某個索引
SELECT * FROM T1 WHERE nextprocess = 1 AND processid IN (8,32,45) 改成: SELECT * FROM T1 (INDEX = IX_ProcessID) WHERE nextprocess = 1 AND processid IN (8,32,45) 則查詢最佳化器將會強行利用索引IX_ProcessID 執行查詢。
11. 消除對大型錶行資料的順序存取
儘管在所有的檢查列上都有索引,但某些形式的WHERE子句強迫最佳化器使用順序存取。如: SELECT * FROM orders WHERE (customer_num=104 AND order_num>1001) OR order_num=1008 解決辦法可以使用並集來避免順序存取: SELECT * FROM orders WHERE customer_num=104 AND order_num>1001 UNION SELECT * FROM orders WHERE order_num=1008 這樣就能利用索引路徑處理查詢。【jacking 資料結果集很多,但查詢條件限定後結果集不大的情況下,後面的語句快】
12. 儘量避免在索引過的字元資料中,使用非打頭字母搜尋。這也使得引擎無法利用索引。
見如下例子: SELECT * FROM T1 WHERE NAME LIKE ‘%L%’ SELECT * FROM T1 WHERE SUBSTING(NAME,2,1)=’L’ SELECT * FROM T1 WHERE NAME LIKE ‘L%’ 即使NAME欄位建有索引,前兩個查詢依然無法利用索引完成加快操作,引擎不得不對全表所有資料逐條操作來完成任務。而第三個查詢能夠使用索引來加快操作,不要習慣性的使用 ‘%L%’這種方式(會導致全表掃描),如果可以使用`L%’相對來說更好;
13. 雖然UPDATE、DELETE語句的寫法基本固定,但是還是對UPDATE語句給點建議:
a) 儘量不要修改主鍵欄位。 b) 當修改VARCHAR型欄位時,儘量使用相同長度內容的值代替。 c) 儘量最小化對於含有UPDATE觸發器的表的UPDATE操作。 d) 避免UPDATE將要複製到其他資料庫的列。 e) 避免UPDATE建有很多索引的列。 f) 避免UPDATE在WHERE子句條件中的列。
14. 能用UNION ALL就不要用UNION
UNION ALL不執行SELECT DISTINCT函式,這樣就會減少很多不必要的資源 在跨多個不同的資料庫時使用UNION是一個有趣的最佳化方法,UNION從兩個互不關聯的表中返回資料,這就意味著不會出現重複的行,同時也必須對資料進行排序,我們知道排序是非常耗費資源的,特別是對大表的排序。 UNION ALL可以大大加快速度,如果你已經知道你的資料不會包括重複行,或者你不在乎是否會出現重複的行,在這兩種情況下使用UNION ALL更適合。此外,還可以在應用程式邏輯中採用某些方法避免出現重複的行,這樣UNION ALL和UNION返回的結果都是一樣的,但UNION ALL不會進行排序。
15. 欄位資料型別最佳化:
a. 避免使用NULL型別:NULL對於大多數資料庫都需要特殊處理,MySQL也不例外,它需要更多的程式碼,更多的檢查和特殊的索引邏輯,有些開發人員完全沒有意識到,建立表時NULL是預設值,但大多數時候應該使用NOT NULL,或者使用一個特殊的值,如0,-1作為預設值。 b. 儘可能使用更小的欄位,MySQL從磁碟讀取資料後是儲存到記憶體中的,然後使用cpu週期和磁碟I/O讀取它,這意味著越小的資料型別佔用的空間越小,從磁碟讀或打包到記憶體的效率都更好,但也不要太過執著減小資料型別,要是以後應用程式發生什麼變化就沒有空間了。修改表將需要重構,間接地可能引起程式碼的改變,這是很頭疼的問題,因此需要找到一個平衡點。 c. 優先使用定長型
-
4 # 程式碼棧
由於不同的資料庫版本,一些常用的最佳化技巧可能隨著資料庫版本的更新發生變化,以下主要把一些常用的最佳化技巧進行總結,使用時可根據實際情況進行調整,對於MySql要善用Explain檢視執行計劃,對於Sql Server要善用執行計劃功能。
1.最佳化第一步建立合適的索引,要儘量避免全表掃描,考慮在where以及order by 設計的列上建立索引。
2.儘量避免在where子句中對欄位進行null值判斷,這樣會導致全表掃描。
3.避免在where子句中用or進行條件連結,可以考慮使用 union all 將查詢進行拆分。
4.儘量用union all 替代union,union和union all的差異主要是前者需要將結果集合並後再進行唯一性過濾操作,這就會涉及到排序,增加大量的CPU運算,加大資源消耗及延遲。當然,union all的前提條件是兩個結果集沒有重複資料。
5.在where子句中避免使用 in 或 not in,應考慮使用exists 或 not exists代替。
6.避免使用 like 模糊查詢,可以考慮使用全文索引。
7.儘量避免在where 子句中對欄位進行表示式操作,這樣會導致全表掃描,(如:select id from table where num/10=2)
8.儘量避免在 where 字句中對欄位進行函式操作。
9.在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。
10.不使用無意義的查詢條件,(如:select id from table where 1=1)。
11.不使用count(*)的計數查詢,要指定具體欄位。
12.索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。
14.儘可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長欄位儲存空間小,可以節省儲存空間,其次對於查詢來說,在一個相對較小的欄位內搜尋效率顯然要高些。
15.查詢語句不可使用 select * from table, 用具體欄位代替*。
16.避免在where子句中出現欄位的型別轉換。
17.注意範圍查詢語句,如between,> ,< 等條件時,後面的索引欄位會失效。
-
5 # 發現你的身邊美食
一、查詢條件精確,針對有引數傳入情況 二、SQL邏輯執行順序 FROM–>JOIN–>WHERE–>GROUP–>HAVING–>DISTINCT–>ORDER–>TOP 三、橫向 查詢需要的欄位 當在SQL語句中連線多個表時,請使用表的別名並把別名字首於每個Column上這樣一來,就可以減少解析的時間並減少那些由Column歧義引起的語法錯誤 四、少做重複工作 控制同一語句的多次執行,特別是一些基礎資料的多次執行是很多程式設計師很少注意的 減少多次的資料轉換 杜絕不必要的子查詢和連線表,子查詢在執行計劃一般解釋成外連線,多餘的連線錶帶來額外的開銷 五、關於零時表#與表變數@ 如果語句很複雜,連線太多,可以考慮用臨時表和表變數分步完成 如果需要多次用到一個大表的同一部分資料,考慮用臨時表和表變數暫存這部分資料 如果需要綜合多個表的資料,形成一個結果,可以考慮用臨時表和表變數分步彙總這多個表的資料 關於臨時表和表變數的選擇,在資料量較多的情況下,臨時表的速度反而更快 SELECT INTO會比CREATE TABLE + INSERT INTO的方法快,但是SELECT INTO會鎖定TEMPDB的系統表SYSOBJECTS、SYSINDEXES、SYSCOLUMNS,在多使用者併發環境下,容易阻塞其他程序 六、子查詢 子查詢可以用IN、NOT IN、EXISTS、NOT EXISTS引入 NOT IN、NOT EXISTS的相關子查詢可以改用LEFT JOIN代替寫法 如果保證子查詢沒有重複 ,IN、EXISTS的相關子查詢可以用INNER JOIN 代替 IN的相關子查詢用EXISTS代替 七、索引 避免對索引欄位進行計算操作 SELECT ID FROM T WHERE NUM/2=100 應改為: SELECT ID FROM T WHERE NUM=100*2 避免在索引欄位上使用NOT,<>,!= 避免在索引列上使用IS NULL和IS NOT NULL 避免在索引列上出現數據型別轉換 避免在索引欄位上使用函式 避免建立索引的列中使用空值 不要對索引欄位進行多欄位連線 WHERE FAME+’. ‘+LNAME=’HAIWEI.YANG’ 應改為: WHERE FNAME=’HAIWEI’ AND LNAME=’YANG’ 八、多表連線 多表連線的時候,連線條件必須寫全,寧可重複,不要缺漏 連線條件儘量使用聚集索引 九、其他 在可以使用UNION ALL的語句裡,使用UNION ALL 避免在WHERE子句中使用IN,NOT IN,OR 避免使用耗費資源的操作,帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL語句會啟動SQL引擎執行,耗費資源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要執行兩次排序 LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘X5400%’則會引用範圍索引。
-
6 # vipplus
下面簡單說幾種提高SQL查詢效率的方法:
1.對查詢進行最佳化,應儘量避免全表掃描,首先應考慮在 where 及 order by 涉及的列上建立索引。
2.應儘量避免在 where 子句中使用!=或<>運算子,否則將引擎放棄使用索引而進行全表掃描。
3.應儘量避免在 where 子句中對欄位進行 null 值判斷,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
可以在num上設定預設值0,確保表中num列沒有null值,然後這樣查詢:
select id from t where num=0
4.應儘量避免在 where 子句中使用 or 來連線條件,否則將導致引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
可以這樣查詢:
select id from t where num=10
union all
select id from t where num=20
5.in 和 not in 也要慎用,否則會導致全表掃描,如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3
6.下面的查詢也將導致全表掃描:
select id from t where name like "%abc%"
若要提高效率,可以考慮全文檢索。
7. 如果在 where 子句中使用引數,也會導致全表掃描。因為SQL只有在執行時才會解析區域性變數,但最佳化程式不能將訪問計劃的選擇推遲到執行時;它必須在編譯時進行選擇。然 而,如果在編譯時建立訪問計劃,變數的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:
select id from t where num=@num
可以改為強制查詢使用索引:
select id from t with(index(索引名)) where num=@num
8.應儘量避免在 where 子句中對欄位進行表示式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改為:
select id from t where num=100*2
9.應儘量避免在where子句中對欄位進行函式操作,這將導致引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)="abc"--name以abc開頭的id
select id from t where datediff(day,createdate,"2005-11-30")=0--‘2005-11-30’生成的id
應改為:
select id from t where name like "abc%"
select id from t where createdate>="2005-11-30" and createdate<"2005-12-1"
10.不要在 where 子句中的“=”左邊進行函式、算術運算或其他表示式運算,否則系統將可能無法正確使用索引。
11.在使用索引欄位作為條件時,如果該索引是複合索引,那麼必須使用到該索引中的第一個欄位作為條件時才能保證系統使用該索引,否則該索引將不會被使用,並且應儘可能的讓欄位順序與索引順序相一致。
12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類程式碼不會返回任何結果集,但是會消耗系統資源的,應改成這樣:
create table #t(...)
13.很多時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)
14.並不是所有索引對查詢都有效,SQL是根據表中資料來進行查詢最佳化的,當索引列有大量資料重複時,SQL查詢可能不會去利用索引,如一表中有欄位sex,male、female幾乎各一半,那麼即使在sex上建了索引也對查詢效率起不了作用。
15. 索引並不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降低了 insert 及 update 的效率,因為 insert 或 update 時有可能會重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有 必要。
16.應儘可能的避免更新 clustered 索引資料列,因為 clustered 索引資料列的順序就是表記錄的物理儲存順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。若應用系統需要頻繁更新 clustered 索引資料列,那麼需要考慮是否應將該索引建為 clustered 索引。
17.儘量使用數字型欄位,若只含數值資訊的欄位儘量不要設計為字元型,這會降低查詢和連線的效能,並會增加儲存開銷。這是因為引擎在處理查詢和連線時會逐個比較字串中每一個字元,而對於數字型而言只需要比較一次就夠了。
18.儘可能的使用 varchar/nvarchar 代替 char/nchar ,因為首先變長欄位儲存空間小,可以節省儲存空間,其次對於查詢來說,在一個相對較小的欄位內搜尋效率顯然要高些。
19.任何地方都不要使用 select * from t ,用具體的欄位列表代替“*”,不要返回用不到的任何欄位。
20.儘量使用表變數來代替臨時表。如果表變數包含大量資料,請注意索引非常有限(只有主鍵索引)。
22.臨時表並不是不可使用,適當地使用它們可以使某些例程更有效,例如,當需要重複引用大型表或常用表中的某個資料集時。但是,對於一次性事件,最好使用匯出表。
23.在新建臨時表時,如果一次性插入資料量很大,那麼可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果資料量不大,為了緩和系統表的資源,應先create table,然後insert。
25.儘量避免使用遊標,因為遊標的效率較差,如果遊標操作的資料超過1萬行,那麼就應該考慮改寫。
26.使用基於遊標的方法或臨時表方法之前,應先尋找基於集的解決方案來解決問題,基於集的方法通常更有效。
27. 與臨時表一樣,遊標並不是不可使用。對小型資料集使用 FAST_FORWARD 遊標通常要優於其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的資料時。在結果集中包括“合計”的例程通常要比使用遊標執行的速度快。如果開發時 間允許,基於遊標的方法和基於集的方法都可以嘗試一下,看哪一種方法的效果更好。
28.在所有的儲存過程和觸發器的開始處設定 SET NOCOUNT ON ,在結束時設定 SET NOCOUNT OFF 。無需在執行儲存過程和觸發器的每個語句後向客戶端傳送 DONE_IN_PROC 訊息。
29.儘量避免大事務操作,提高系統併發能力。
30.儘量避免向客戶端返回大資料量,若資料量過大,應該考慮相應需求是否合理。
-
7 # 是國鋒呀
1.正確的建立合適的索引是提成生資料庫查詢的基礎。
2.索引是為了加速對錶中資料行的檢索而建立的一種分散儲存的資料資料結構。如圖以mysql(innodb引擎)為例
3.為什麼要用索引?
a.索引能極大的減少儲存引擎需要掃描的資料量。
b.索引可以把隨機IO變成順序IO。
c.索引可以幫助我們在進行分組、排序等操作時,避免使用臨時表。
4.sql前面加上 explain select Column Name1,Column Name2,Column Name3 from table;
排查是否走索引依次從好到差:system,const,eq_ref,ref,fulltext,ref_or_null,unique_subquery,index_subquery,range,index_merge,index,ALL。
5.索引注意要點
a.選擇離散度高的列建索引.
b.索引列的資料長度能少則少。
c.索引一定不是越多越好,越全越好,一定是建合適的。
d.匹配列字首可用到索引 like 9999%,like %9999%、like %9999用不到索引;
e.Where 條件中 not in 和 <>操作無法使用索引;匹配範圍值,order by 也可用到索引
f.多用指定列查詢,只返回自己想到的資料列,少用select *;
g.聯合索引中如果不是按照索引最左列開始查詢,無法使用索引;聯合索引中精確匹配最左前列並範圍匹配另外一列可以用到索引;
h.聯合索引中如果查詢中有某個列的範圍查詢,則其右邊的所有列都無法使用索引。
回覆列表
MySQL索引對資料檢索的效能至關重要,盲目的增加索引不僅不能帶來效能的提升,反而會消耗更多的額外資源。
索引是用於快速查詢記錄的一種資料結構。索引就像是資料庫中資料的目錄,資料庫在查詢時,首先在索引中找到匹配的值,然後根據這個匹配值找到對應的資料行。
聚簇索引的順序就是資料的物理儲存順序,索引中資料域儲存的就是實際的資料,一個表最多隻能有一個聚簇索引,適用於查詢多行資料,不適用於頻繁修改的列,一般在主鍵上建立。
非聚簇索引順序與資料物理排列順序無關,索引中儲存的內容為實際資料的地址,適應於查詢單行資料。
普通索引,即平時建立的普通索引。
唯一索引,索引所在的列或列組合的值是全表唯一的。
全文索引,MySQL從3.23.23版開始支援全文索引,它查詢的是文中的關鍵詞,而不是直接比較索引中的值。
單列索引,在單列上建立的索引。
組合索引,在多個列上建立的索引。
最左字首查詢:where子句中有a、b、c三個查詢條件,建立一個組合索引abc(a,b,c),最左字首的概念是說以組合索引最左邊的列a組合成的查詢條件,如(a,b,c)、(a,b)、(a,c),這三種情況的查詢條件都會使用abc索引,和where子句中a、b、c出現的順序沒關係,可以是where c=? and b=? and a=?,但(b,c)組合不會使用索引,即where c=? and b=?。
哪些列適合建立索引:
1.經常作為查詢條件的列;
2.經常作為排序條件的列;
3.經常作為join條件的列;
4.經常被查詢的列。
哪些列不適合建立索引:
1.資料頻繁被修改的列,資料被修改,索引需要做相應的修改,消耗資源; 2.區分度不是很高的列,如性別,列值重複性太大,索引效果不是很明顯; 3.不是經常被作為查詢條件、排序條件、連線條件的列。
經驗總結:
1.列上進行函式計算將不會使用索引;
2.對於建立索引的列,避免儲存NULL,NULL會使索引更加複雜、效率變低,可以使用NOT NULL進行約束;
3.對於模糊查詢like "%abc%",將不會使用索引,而like "abc%"將會使用索引;
4.對於not in、not exists、!=等負向查詢將不會使用索引;
5.每次查詢只使用一個索引,如果where條件使用了索引,order by將不再使用索引;
6.對於where子句中有多個查詢條件的,單列索引的效率不如複合索引,因為查詢每次只能使用一個索引;
7.MySQL只對以下運算子才使用索引:<、<=、=、>、>=、between、in,但是需要注意in的範圍值不要太多;
8.union all可以使用索引,但本身效率不是很高,不建議使用;
9.列上進行型別轉換的將不會使用索引;
10.老版本MySQL對OR條件不使用索引,新版本才支援,不建議使用OR。