MySQL數(shù)據庫優(yōu)化建議

50多條使用mysql數(shù)據庫優(yōu)化建議

1.對查詢進行優(yōu)化,應盡量避免全表掃描,首先應考慮在WHEREORDER BY涉及的列上建立索引。

缺省情況下建立的索引是非群集索引,但有時它并不是最佳的。在非群集索引下,數(shù)據在物理上隨機存放在數(shù)據頁上。合理的索引設計要建立在對各種查詢的分析和預測上。一般來說:

a.有大量重復值,且經常有范圍查詢(>,<,>=,<=)和ORDER BYGROUP BY發(fā)生的列,可考慮建立群集索引;

b.經常同時存取多列,且沒列都含有重復值,可考慮建立組合索引,選擇度高的列建議作為索引的第一個字段;

c.組合索引要盡量使關鍵查詢形成索引覆蓋,其前導列一定是使用最頻繁的列。索引雖有助于提高性能,但不是索引越多越好,恰好相反,過多的索引會導致系統(tǒng)低效。用戶在表中沒加進一個索引,維護索引集合就要做相應的更新工作。

2.應盡量避免在WHERE子句中對字段進行NULL值判斷,否則將導致引擎放棄使用索引而進行全表掃描;

    SQL代碼:SELECT id FROM t WHERE num IS NULL;
    可以在num上設置默認值0,確保表中num列沒有null值,然后這樣查詢:
    SQL代碼:SELECT id FROM t WHERE num = 0;

3.應盡量避免在WHERE子句中使用!=<>操作符,否則引擎將放棄使用索引而進行全表掃描。

4.應盡量避免在WHERE子句中使用OR來連接條件,否則將導致引擎放棄使用索引而進行全表掃描。

    SQL代碼:SELECT id FROM t WHERE num = 10 OR num = 20;
    可以這樣查詢:
    SQL代碼:SELECT id FROM t WHERE num = 10 UNION ALL SELECT id FROM t WHERE num = 20;

5.INNOT IN也要慎用,否則會導致全表掃描,如:

    SQL代碼:SELECT id FROM t WHERE num IN(1,2,3);

對于連續(xù)的數(shù)值,能用BETWEEN就不要用IN

    SQL代碼:SELECT id FROM t WHERE num BETWEEN 1 AND 3;

6.下面的查詢也將導致全表掃描:

    SQL代碼:SELECT id FROM t WHERE name LIKE '%c%';

若要提高效率,可以考慮全文檢索。

7.如果在WHERE子句中使用參數(shù),也會導致全表掃描。因為SQL只有在運行時才會解析局部變量,但優(yōu)化程序不能將訪問計劃的選擇推遲到運行時,它必須在編譯時進行選擇。然而,如果在編譯時建立訪問計劃,變量的值還是未知的,因而無法作為索引選擇的輸入項。如下面語句將進行全表掃描:

    SQL代碼:SELECT id FROM t WHERE num = @numl;

可以改為強制查詢使用索引:

    SQL代碼:SELECT id FROM t WITH(INDEX(索引名)) WHERE num = @num;

8.應盡量避免在WHERE子句中對字段進行表達式操作,這將導致引擎放棄使用索引而進行全表掃描:

    SQL代碼:SELECT id FROM t WHERE num / 20 = 100;

可以這樣查詢:

    SQL代碼:SELECT id FROM t WHERE num = 100 * 2;

9.應盡量避免在WHERE子句中對該字段進行函數(shù)操作,這將導致引擎放棄使用索引而進行全表掃描,如:

    SQL代碼:SELECT id FROM t WHERE SUBSTRING(name, 1, 3) = 'name';
    應改為:
    SQL代碼:SELECT id FROM t WHERE name LIKE 'abc%';

10.不要在WHERE子句中的=左邊進行函數(shù)、算數(shù)運算或其他表達式運算,否則系統(tǒng)將可能無法正確使用索引。

11.在使用索引字段作為條件時,如果該索引是復合索引,那么必須使用到該索引中的第一個字段作為條件時才能保證系統(tǒng)使用該索引,否則該索引將不會被使用,并且應盡可能的讓字段順序與索引順序一致、

12.不要寫一些沒有意義的查詢,如需要生成一個空表結構:

    SQL代碼:SELECT col1, col2 INTO #t FROM t WHERE 1 = 0;

這類代碼不會返回任何結果集,但是會消耗系統(tǒng)資源的,應改成這樣:

    SQL代碼:CREATE TABLE #t(...);

13.很多時候用EXISTS代替IN是個好的選擇:

    SQL代碼:SELECT num FROM a WHERE num IN (SELECT num FROM b);

用下面的語句替換:

    SQL代碼:SELECT num FROM a WHERE EXISTS (SELECT 1 FROM b WHERE num = a.num);

14.并不是所有的索引都對查詢有效,SQL是根據表中數(shù)據來進行查詢優(yōu)化的,當索引列有大量數(shù)據重復時,SQL查詢可能不會去利用索引,如一表中有字段male、female幾乎各占一半,那么即使在這一列上建立了索引也對查詢效率起不了作用。

15.索引并不是越多越好,索引固然可以提高相應的SELECT的效率,但同時也降低了INSERTUODATE的效率,因為INSERTUPDATE時有可能會重建索引,索引怎樣檢索因需要慎重考慮,視具體情況而定。一個表的索引數(shù)最好不要超過6個,若太多則應該考慮一些不常用到的列上建的索引是否有必要。

16.應盡可能的避免更新CLUSTERED索引數(shù)據列的順序就是表記錄的物理存儲順序,一旦該列值改變將導致整個表記錄的順序的調整,會耗費相當大的資源。所應用系統(tǒng)需要頻繁更新CLUSTERED索引數(shù)據列,那么需要考慮是否應將該索引建為CLUSTERED索引。

17.盡量使用數(shù)字型字段,若只含數(shù)值信息的字段盡量不要設計為字符型,這會降低查詢和連接的性能,并會增加存儲開銷。這是因為引擎在處理查詢和連接時會逐個比較字符串中每一個字符,而對于數(shù)字型而言,只需要比較一次就夠了。

18.盡可能的使用VARCHAR/NVARCHAR代替CHAR/NCAHR,因為首先變長字段存儲空間小,可以節(jié)省存儲空間,其次對于查詢來說,在一個相對較小的字段內搜索效率顯然是要高一些。

19.任何地方都不要使用SELECT * FROM t;,用具體的字段列表代替“*”,不要返回用不到的任何字段。

20.盡量使用表變量來代替臨時表。如果表變量包含大量數(shù)據,請注意索引非常有限(只有主鍵索引)。

21.避免頻繁創(chuàng)建和刪除臨時表,以減少系統(tǒng)表資源的消耗。

22.臨時表并不是不可使用,適當?shù)厥褂盟T可以使某些例程更有效,例如,當需要重復引用大型表或常用表中的某個數(shù)據集時。但是,對于一次性事件,最好使用導出表。

23.在新建臨時表時,如果一次性插入數(shù)據量很大,那么可以使用SELECT INTO代替CREAT TABEL,避免造成大量LOG,以提高速度,如果數(shù)據量不大,為了緩和系統(tǒng)表的資源,應先CREATE TABLE,然后INSERT

24.如果使用到了臨時表,在存儲過程的最后務必將所有臨時表顯式刪除,先TRUNCATE TABLE,然后DROP TABLE,這樣可以避免系統(tǒng)表的較長時間鎖定。

25.盡量避免使用游標,因為游標的效率較差,如果游標操作的數(shù)據超過1萬行,那么就應該考慮該下改寫。

26.使用基于游標的方法或臨時表方法之前,應先尋找基于集的解決方案來解決問題,基于集的方法通常更有效。

27.與臨時表一樣,游標并不是不可使用,對小型數(shù)據集使用FAST_FORWARD游標通常要優(yōu)于其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數(shù)據時。在結果集中包括“合計”的例程通常要比使用游標執(zhí)行的速度快。如果開發(fā)時間允許,基于游標的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更好。

28.在所有的存儲過程和觸發(fā)器的開始處設置SET NOCOUNT ON,在結束時設置SET NOCOUNT OFF。無需在執(zhí)行存儲過程和觸發(fā)器的每個語句后向客戶端發(fā)送DONE_IN_PROC消息。

29.盡量避免大事務操作,提高系統(tǒng)并發(fā)能力。

30.頂起分析表和檢查表。

分析表的語法:ANALYZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tb1_name[, tb1_name]...以上語句用于分析和存儲表的關鍵字分布,分析的結果將可以使得系統(tǒng)得到準確的統(tǒng)計信息,使得SQL能夠生成正確的執(zhí)行計劃。如果用戶感覺實際執(zhí)行計劃并不是預期的執(zhí)行計劃,執(zhí)行一次分析表可能會解決問題。在分析期間,使用一個讀取鎖定對表進行鎖定。這對于MyISAMDBBDBInniDB有作用。

例如分析一個數(shù)據表:ANALYZE TABLE table_name

檢查表的語法:CHECK TABLE tb1_name[, tb1_name]...[option]...option = {QUICK | FAST | MEDIUM | EXTENDED | CHANGED}

檢查表的作用是檢查一個或者多個表是否有錯誤,CHECK TABLEMyISAMInnoDB表有作用,對于MyISAM表,關鍵字統(tǒng)計數(shù)據被更新。

CHECK TABLE也可以檢查視圖是否有錯誤,比如在視圖定義中被引用的表不存在。

31.定期優(yōu)化表

優(yōu)化表的語法:OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tb1_name [, tb1_name]...如果刪除了標的一大部分,或者如果已經對含有可變長度行的表(含有VARCHARBLOB或者TEXT列的表)進行更多更改,則應使用OPTIMIZE TABLE命令來進行表優(yōu)化。這個命令可以將表中的空間碎片進行合并,并且可以消除由于刪除或者更新造成的空間浪費,但OPTIMIZE TABLE命令只對MyISAMBDBInnoDB表起作用。

例如:OPTIMIZE TABLE table_name;

注意:ANALYZECHECKOPTIMIZE執(zhí)行期間將對表進行鎖定,因此一定注意要在MySQL數(shù)據庫不繁忙的時候執(zhí)行相關的操作。

32.存儲引擎的選擇。如果數(shù)據表需要事務處理,應該考慮使用InnoDB,因為它完全符合ACID特性。如果不需要事務處理,使用默認存儲引擎MyISAM是比較明智的。

MyISAM適用于一些需要大量查詢的應用,但其對于有大量寫操作并不是很好。設置你只是需要UPDATE一個字段,整個表都會被鎖起來,而別的進程,就算是讀進程都無法操作直到讀操作完成。另外,MyISAM對于SELECT COUNT(*)這類的計算是超快無比的。

33.InnoDB的趨勢會是一個非常復雜的存儲引擎,對于一些小的應用,它會比MyISAM還慢。但是它支持行鎖,于是在寫操作比較多的時候,會更優(yōu)秀。并且,它還支持更多的高級操作,比如,事務。

34.EXPLAIN你的SELECT查詢

使用EXPLAIN關鍵字可以讓你知道MySQL是如何處理你的SQL語句的。這可以幫助你分析你的查詢語句或是表結構的性能瓶頸。

EXPLAIN的查詢結果還會告訴你你的索引主鍵如何被利用,你的數(shù)據表是如何被搜索和排序的……等等,等等。

挑一個你的SELECT語句(推薦挑選那個最復雜的,有多表級聯(lián)的),把關鍵字EXPLAIN加到前面。你可以使用phpmyadmin來做這個事。然后,你會看到一張表格。下面的這個示例中,我們忘記加上了GROUP_ID索引,并且有表連接:

35.當是要一行數(shù)據是使用LIMIT 1

當你查詢表的有些時候,你已經知道結果只會有一條,但因為你可能需要去FETCH游標,或是你也許會去檢查返回的記錄數(shù)。在這種情況下,加上LIMIT 1可能增加性能。這樣MySQL引擎會在找到一條數(shù)據后停止搜索,而不是繼續(xù)往后查找下一條符合記錄的數(shù)據。

    沒有效率的:
    $r = MYSQL_QUERY("SELECT * FROM user WHERE country = 'China'");IF(MYSQL_NUM_ROWS($r) > 0){//...}
    有效率的:
    $r = MYSQL_QUERY("SELECT * FROM user WHERE country = 'China' LIMIT 1");IF(MYSQL_NUM_ROWS($r) > 0){//...}

36.在JION表的時候使用相同類型的列,并將其索引

如果你的應用程序有很多JION查詢,你應該確認兩個表中JION字段是被建過索引的。這樣MySQL內部會啟動為你優(yōu)化JION的語句的機制。

而且,這些被用來JION的字段,應該是相同的類型的。例如:如果你要把DECIMAL字段和一個INT字段JION在一起,MySQL就無法使用它們的索引。對于那些STRING類型,還需要有相同的字符集才行。

    //在STATE中查找company
    $r = MYSQL_QUERY("SELECT company_name
        FROM users
        LEFT JION companies ON (users.state = companies.state)
        WHERE users.id = $user_id");

37.千萬不要ORDER BY RAND()

想打亂返回的數(shù)據行?隨機挑一個數(shù)據?真不知道誰發(fā)明了這種用法,但很多新手很喜歡這樣用。但你卻不了解這樣做有多么可怕的性能問題。

=如果你真的想把返回的數(shù)據行打亂了,你有N種方法可以達到這個目的,這樣使用只讓你的數(shù)據庫性能懲治書記的下降。這里的問題是:MySQL會不得不去執(zhí)行RAND()函數(shù)(很耗CPU時間),而且這是為了每一行汲取去記行,然后再對其排序。就算是你用了LIMIT 1也無濟于事(因為要排序)

下面的示例是隨機挑一條記錄

    //千萬不要這樣做:
    $r = MYSQL_QUERY("SELECT username FROM user ORDER BY RAND() LIMIT 1");
    //這樣做會更好:
    $r = MYSQL_QUERY("SELECT COUNT(*) FROM user");
    $d = MYSQL_FETCH_ROW($r);
    $rand = MT_RAND(0, $d[0] - 1);
    $r = MYSQL_QUERY("SELECT username FROM user LIMIT $rand, 1");

38.永遠為每一張表設置一個ID

我們應該為數(shù)據庫里的每張表都設置一個ID作為其主鍵,而且最好的是一個INT型的(推薦使用UNSIGNED),并設置上自動增加的AUTO_INCREMENT標志。

就算是你users表有一個主鍵叫“email”的字段,你也別讓它成為主鍵。使用VARCHAR類型來當主鍵會使性能下降。另外,在你的程序中,你應該使用表的ID來構造你的數(shù)據結構。

而且,在MySQL數(shù)據引擎下,還有一些操作需要使用主鍵,在這些情況下,主鍵的性能和設置變得非常重要,比如,集群,分區(qū)……

在這里,只有一個情況是例外,那就是“關聯(lián)表”的“外鍵”。比如:有一個“學生表”有學生的ID,有一個“課程表”有課程ID,那么“成績表”就是“關聯(lián)表”了,其關聯(lián)了學生表和課程表嗎,在成績表中,學生ID和課程ID叫做“外鍵”其共同組成主鍵。

39.從PROCEDURE ANALYSE()取得建議

PROCEDURE ANALYSE()會讓MySQL幫你去分析你的字段和其實際的數(shù)據,并會給你一些有用的建議。只有表中有實際的數(shù)據,這些建議才會變得有用,因為要做一些大的決定是需要有數(shù)據作為基礎的。

例如,如果你創(chuàng)建一個INT字段作為你的主鍵,然而并沒有太多的數(shù)據,那么,PROCEDURE ANALYSE()會建議你把這個字段的類型改為MEDIUMINT。或是你使用了一個VARCHAR字段,因為數(shù)據不多,你可能會得到一個讓你把它改成ENUM的建議。這些建議可能因為數(shù)據不夠多,所以決策做得不夠準。

一定要注意,這些只是建議,只有當你的表里的數(shù)據越來越多是,這些建議才會變得準確。一定要記住,你才是最終做決定的人。

40.字段盡可能的使用NOT NULL約束

除非你有一個很特別的原因去使用NULL值,你應該總是讓你的字段保持NOT NULL。這看起來好像有點爭議,請往下看:

首先,問問自己“Empty”和“NULL”有多大區(qū)別(如果是INT,那就是0和NULL)?如果你覺得它們之間沒什么區(qū)別,那么你就不要使用NULL
。(你知道嗎?在Oracle里,NULLEmpty的字符串是一樣的!)

不要以為NULL不需要空間,其需要額外的空間,并且,在你進行比較的時候,你的程序會更復雜。當然,這里并不是說你就不要使用NULL了,現(xiàn)實情況是很復雜的,依然在有些情況下,你需要使用NULL值。

下面摘自MySQL自己的文檔:

“NULL columns require additional space in the row to record whether their values are NULL. For MyISAM tables, each NULL column takes one bit extra, rounded up to the nearest byte.”

如果你要保存NULL,手動去設置它,而不是把它設為默認。建議使用0、特殊值或者空串代替NULL

41.Prepared Statements

Prepared Statements很像存儲過程,是一種運行在后臺的SQL語句集合,我們可以從使用Prepared Statements獲得很多好處,無論是性能問題還是安全問題。

Prepared Statements可以檢查一些你綁定好的變量,這樣可以保護你的程序不會受到“SQL注入式攻擊”,當然,你也可以手動地檢查你的這些變量,然而,手動的檢查容易出問題,而且很經常會被程序員忘了。當我們使用一些framework或是ORM的時候,這樣的問題會好一些。

在性能方面,當一個相同的查詢被使用多次的時候,這回為你帶來客觀的性能優(yōu)勢。你可以給這些Prepared Statements定義一些參數(shù),而MySQL只會解析一次。

因為最新版本的MySQL在傳輸Prepared Statements時使用二進制形式,所以這會使得網絡傳輸非常有效率。

當然,也有一些情況下,我們需要避免使用Prepared Statements,因為其不支持查詢緩存。但據說版本5.1后支持了。

42.把IP地址存成UNSIGNED INT

很多程序員都會創(chuàng)建一個VARCHAR(15)字段來存放字符串形式的IP而不是整型的IP。如果你用整型來存放,只需要4個字節(jié),并且你可以有定長的字段。而且,這會為你帶來查詢上的優(yōu)勢,尤其是當你需要使用這樣的WHERE條件:IP BETWEEN ip1 AND ip2

我們必需要使用UNSIGNED INT因為IP地址會使用整個32位的無符號整型。

而你的查詢,你可以使用INET_NTOA()把一個整型轉成一個字符串IP。在PHP中,也有這樣的函數(shù)IP2LONG()LONG2IP()

43.固定長度的表會更快

如果表中所有字段都是“固定長度”的,整個表會被認為是“static”或“fixed-length”。例如,表中沒有如下類型的字段:VARCHARTEXTBLOB。只要你包括了其中一個這些字段,那么這個表就不是“固定長度靜態(tài)表”了,這樣,MySQL引擎會用另一種方法來處理。

固定長度的表會提高性能,因為MySQL搜索得會更快一些,因為這些固定的長度是很容易計算下一個數(shù)據的偏移量的,所以讀取的自然也會很快。而如果字段不是定長的,那么,每一次要找下一條的話,需要程序找到主鍵。

而且,固定長度的表也更容易被緩存和重建。不過,唯一的副作用是,固定長度的字段會浪費一些空間,因為定長的字段無論你用不用,他都要分配那么多的空間。

使用“垂直分割”技術,你可以分割你的表成為兩個:一個是定長的,一個是不定長的。

45.垂直分割表

“垂直分割”是一種把數(shù)據庫中的表按列變成幾張表的方法,這樣可以降低表的復雜度和字段的數(shù)目,從而達到優(yōu)化的目的。

示例一:在users表中有一個字段是家庭住址,這個字段是可選字段,相比起,而且你在數(shù)據庫操作的時候除了個人信息外,你并不需要經常讀取或是改寫這個字段。那么,你為什么不把他放在另一張表中呢?這樣會讓你的表有更好的性能,大家想想是不是,大量的時候,我對于用戶表來說,只有用戶ID、用戶名、口令和用戶角色等會被經常使用。小一點的表總會有好的性能。

示例二:你有一個叫“l(fā)ast_login”的字段,它會在每次用戶登錄時被更新。但是,每次更新時會導致該表的查詢緩存被清空。所以,你可以把這個字段放在另一個表中,這樣就不會影響你對用戶ID、用戶名和用戶角色的不停讀取了,因為查詢緩存會幫你增加很多性能。

另外,你需要注意的是,這些被分出去的字段所形成的表,你不會經常性地去JION他們,不然的話,這樣的性能會比不分割時還要差,而且,會是指數(shù)級地下降。

46.拆分大的DELETEINSERT語句

如果你需要在一個在線的網站上去執(zhí)行一個大的DELETEINSERT查詢,你需要非常小心,要避免你的操作讓你的整個網站停止服務,因為這兩個操作是會鎖表的,表一鎖住了,別的操作都進不來了。

Apache會有很多的子進程或線程。所以,其工作起來想當有效率,而我們的服務器也不希望有太多的子進程、線程和數(shù)據庫鏈接,這是極大的占服務器資源的事情,尤其是內存。

如果你把你的表鎖上一段時間,比如30秒鐘,那么對于一個有很高訪問量的站點來說,這30秒所積累的訪問進程、線程、數(shù)據庫鏈接、打開的文件數(shù),可能不僅僅會讓你的WEB服務Crash,還可能會讓你整臺服務器馬上掛了。

所以,如果你有一個很大的處理,你一定要把其拆分,使用LIMIT條件是一個很好的辦法。下面是一個示例:

    WHILE(1){
        //每次只做1000條
        MYSQL_QUERY("DELETE FROM logs WHERE log_date <= '2009-11-01' LIMIT 1000");
        IF(MYSQL_AFFECTED_ROWS() == 0){
            //沒得刪了,退出!
            //BREAK;
        }
        //每次都要休息一會兒
        USLEEP(50000)
    }

47.越小的列會越快

對于大多數(shù)的數(shù)據庫引擎來說,硬盤操作可能是最重大的瓶頸。所以,把你的數(shù)據變得緊湊會對這種情況非常有幫助,因為這減少了對硬盤的訪問。

參看MySQL的文檔Storage Requirements查看所有的數(shù)據類型。

如果一個表只有幾列罷了(比如說字典表,配置表),那么,我們就沒理由使用INT來做主鍵,使用MEDIUMINTSMALLINT、或是更小的TINYINT會更經濟一些。如果你不需要記錄時間,使用DATE要比DATETIME好很多。

當然,你也需要留夠足夠的擴展空間,參看Slashdot的例子(2009年11月06日),一個簡單的ALTER TABLE語句花了3個多小時,因為里面有一千六百萬條數(shù)據。

48.使用一個對象關系映射器(Object Relational Mapper)

使用ORM你能獲得可靠的性能增長。一個ORM可以做的所有事情,也能被手動地邊寫出來,但是這需要一個高級專家。

ORM的最重要的是“LAZY LOADING”,也就是說,只有在需要去取值的時候才會去真正地去做。但你也需要小心這種機制的副作用,因為這很有可能會因為要去創(chuàng)建很多很多小的查詢,反而會降低性能。ORM還可以把你的SQL語句打包成一個事務,這會比單獨執(zhí)行它們快得多得多。

49.小心“永久鏈接”

“永久鏈接”的目的是用來減少重新創(chuàng)建MySQL鏈接的次數(shù)。當一個鏈接被創(chuàng)建,它會永遠處在連接的狀態(tài),就算是數(shù)據庫操作已經結束了。而且,自從我們的Apache開始重用它的子進程后——也就是說,下一次的HTTP請求會重用Apache的子進程,并重用相同的MySQL鏈接。

50.范圍列(>,<,BETWEEN AND)可以用到索引,但是范圍列后面的列無法用到索引。同時,索引最多用于一個范圍列,因此如果查詢條件中有兩個范圍列則無法全用到作引。

51.如果需要在大字段上建立索引,可以考慮使用前綴索引。

建立前綴索引的語法為:

    ALTER TABLE table_name ADD KEY(column_name(prefix_length));

52.將大字段、訪問頻率低的字段拆分到單獨的表中存儲。分離冷熱數(shù)據,有利于有效利用緩存,防止讀入無用的冷數(shù)據,較少磁盤IO,同時保證熱數(shù)據常駐內存提高緩存命中率。

53.MySQL的新增和修改列的操作相當于重建表,表設計要一步到位,盡量避免大表的DDL操作。(TIPS:可以預定義一些列留作將來業(yè)務擴展,如:當前只需要10個字段,考慮到未來發(fā)展,可以預留10個字段,表上總共創(chuàng)建20個字段)

54.為了降低索引維護成本,禁止冗余索引,增大IO壓力。(a,b,c)、(a,b),后者為冗余索引。可以利用前綴索引來達到加速目的,減輕維護負擔。

55.WHERE子句中的數(shù)據掃描不超過表總數(shù)據量的30%。

如何選擇prefic_length的長度,具體參考:前綴索引,一種優(yōu)化索引大小的解決方案

補充:

  • 在海量查詢時盡量少用格式轉換。

  • 任何對列的操作都將導致表掃描,它包括數(shù)據庫教程函數(shù)、計算表達式等等,查詢時要盡可能將操作移至符號右邊。

  • INOR子句常會使用工作表,是索引失效。如果不產生大量重復值,可以考慮把子句拆開。拆開的子句中應該包含索引。

  • 盡量少用CLOBTEXTBLOB大類型。

  • 如果你的數(shù)據只有你所知的少量的幾個量,最好使用ENUM類型。

    ENUM類型是非常快和緊湊的。在實際上,其保存的是TINYINT,但其外表上顯示為字符串。這樣一來,用這個字段來做一些選項列表變得相當完美。

    如果你有一個字段,比如“性別”,“國家”,“民族”,“狀態(tài)”或者“部門”,你知道這些字段的取值是有限而且固定的,那么,你應該使用ENUM而不是VARCHAR

    MySQL也有一個“建議”(見第十條)告訴你怎么去重新組織你的表結構。當你有一個VARCHAR字段時,這建議會告訴你把其改成ENUM類型。使用PROCEDURE ANALYSE()你可以得到相關的建議。

  • 合理運用庫、分表、與分區(qū)表提高數(shù)據存放和提取速度。具體參考:MySQL分表和分區(qū)的區(qū)別、分庫分表區(qū)別

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內容