一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

MySQL高效查詢的書寫習(xí)慣的養(yǎng)成

 新進(jìn)小設(shè)計(jì) 2020-02-15

How to write efficient MySQL query statements

  • How to write efficient MySQL query statements

    • WHERE子句中的書寫注意事項(xiàng)
    • 模糊查詢(like)時(shí)需要注意的事項(xiàng)
    • 索引
    • 字段類型
    • 表連接時(shí)的注意事項(xiàng)
    • 其他注意事項(xiàng)

WHERE子句中的書寫注意事項(xiàng)

  • 首先應(yīng)考慮在 where 及 order by 涉及的列上建立索引。
  • 下列操作會(huì)導(dǎo)致引擎放棄使用索引而進(jìn)行全表掃描,是應(yīng)盡量避免的。

    • 1).在where 子句中使用!=<>操作符
    • 2).在where子句中對(duì)字段進(jìn)行null值判斷
      如:

      select id from t where num is null;

      可以在num上設(shè)置默認(rèn)值0,確保表中num列沒(méi)有null值,然后這樣查詢:

      select id from t where num=0;
    • 3).在where子句中使用 or 來(lái)連接條件
      如:

      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;
    • 4).in 和 not in 也要慎用
      如:

      select id from t where num in(1,2,3);

      對(duì)于連續(xù)的數(shù)值,能用between就不要用in
      如:

      select id from t where num between 1 and 3;

      很多時(shí)候可以用exists代替in
      如:

      select num from a where num in(select num from b);

      用下面的語(yǔ)句替換:

      select num from a where exists(select 1 from b where num=a.num);
    • 5).在where子句中使用參數(shù)
      因?yàn)镾QL只有在運(yùn)行時(shí)才會(huì)解析局部變量,但優(yōu)化程序不能將訪問(wèn)計(jì)劃的選擇推遲到運(yùn)行時(shí),它必須在編譯時(shí)進(jìn)行選擇。
      如果在編譯時(shí)建立訪問(wèn)計(jì)劃,變量的值還是未知的,因而無(wú)法作為索引選擇的輸入項(xiàng)。
      如下面語(yǔ)句將進(jìn)行全表掃描:

      select id from t where num=@num;

      可以改為強(qiáng)制查詢使用索引:

      select id from t with(index(索引名)) where num=@num
    • 6).在where子句中對(duì)字段進(jìn)行函數(shù)、算術(shù)運(yùn)算或其他表達(dá)式運(yùn)算
      如:

      select id from t where num/2=100;
      select id from t where date(createdate)>='2016-07-01';

      應(yīng)改為:

      select id from t where num=100*2
      select id from t where createdate>='2005-11-30 00:00:00';

模糊查詢(like)時(shí)需要注意的事項(xiàng)

  • 左右都需要模糊匹配時(shí),會(huì)導(dǎo)致全表掃描;

    select id from t where tablename like '%abc%'
  • 若要提高效率,可從以下三點(diǎn)著手:

    • a.不以"%"開始,如:select id from t where tablename like 'abc%'。
    • b.如果必須使用like "%xxx" 的sql,可基于REVERSE()函數(shù)來(lái)創(chuàng)建一個(gè)函數(shù)索引。

      參考:http://blog.csdn.net/wangjunj...
    • c.可以考慮全文檢索。
      首先如果表默認(rèn)是innoDB,這種表的類型不支持全文檢索,所以要先改變其類型為MyISAM

      alter table song engine=MyISAM;

      然后要在對(duì)應(yīng)的要進(jìn)行查找的字段上面建立全文檢索的索引:

      alter table add fulltext index(songname);

      如果要同時(shí)對(duì)多個(gè)字段進(jìn)行檢索可以這樣:

      alter table add fulltext index(songname,singername);

      完成以上步驟后,就可以對(duì)表進(jìn)行全文檢索了。
      例如:

      select * from song where match(singername) against('周杰倫') ;

      或者多字段:

      select * from song where match(singername,songname) against('風(fēng)雨');
      MYSQL目前可能只支持英文字符的全文搜索,如需使用全文檢索需要把中文轉(zhuǎn)化為拼音。
      可以在表里面為需要檢索的字段添加一個(gè)拼音字段,檢索的時(shí)候直接對(duì)拼音進(jìn)行檢索。
      參考:http://blog.sina.com.cn/s/blo...

索引

  • 復(fù)合索引
    在使用索引字段作為條件時(shí),如果該索引是復(fù)合索引,那么必須使用到該索引中的第一個(gè)字段作為條件才能保證系統(tǒng)使用該索引,并且應(yīng)盡可能的讓字段順序與索引順序相一致。
  • 當(dāng)索引列有大量數(shù)據(jù)重復(fù)時(shí),SQL查詢可能不會(huì)去利用索引
    并不是所有索引對(duì)查詢都有效,SQL是根據(jù)表中數(shù)據(jù)來(lái)進(jìn)行查詢優(yōu)化的;
    如一表中有字段sex[male|female]幾乎各一半,那么即使在sex列上建了索引也對(duì)查詢效率起不了作用。

    這個(gè)時(shí)候可以用ENUM(枚舉類型),而不是VARCHAR,并對(duì)表結(jié)構(gòu)進(jìn)行優(yōu)化(select column from table_name procedure analyse();)

    例如:

    SELECT loan_period FROM cbs_bsns_loan PROCEDURE ANALYSE();
  • 索引并不是越多越好
    索引固然可以提高相應(yīng)的select的效率,但同時(shí)也降低了insertupdate的效率;
    因?yàn)?code>insert或update時(shí)有可能會(huì)重建索引,所以怎樣建索引需要慎重考慮,視具體情況而定。
    原則上,一個(gè)表的索引數(shù)最好不要超過(guò)6個(gè),若太多則應(yīng)考慮一些不常使用到的列上建的索引是否有必要。
  • 盡可能的避免更新clustered索引數(shù)據(jù)列
    clustered索引數(shù)據(jù)列的順序就是表記錄的物理存儲(chǔ)順序,一旦該列值改變將導(dǎo)致整個(gè)表記錄的順序的調(diào)整,會(huì)耗費(fèi)相當(dāng)大的資源。
    若應(yīng)用系統(tǒng)需要頻繁更新clustered索引數(shù)據(jù)列,那么需要考慮是否應(yīng)將該索引建為clustered索引。

    MySQL InnoDb中的索引分為 Clustered Index (聚簇索引)和 Secondary Index (二級(jí)索引);
    Clustered Index:每一個(gè)InnoDB表都有一個(gè)特殊的索引,叫做clustered index,通常來(lái)講,clustered indexplrimary key是同一個(gè)意思。

    InnoDB選擇clustered index原則如下:
    ①如果表上定義了primary key,則使用primary key作為clustered index。
    ②如果沒(méi)有定義primary key,選擇第一個(gè)非空的UNIQUE索引作為clustered index。所以,如果表只有一個(gè)非空的UNIQUE索引,那么InnoDB就把它當(dāng)作主健了。
    ③如果即沒(méi)有primary key,也沒(méi)有合適的UNIQUE索引,InnoDB內(nèi)部產(chǎn)生一個(gè)隱藏列,這個(gè)列包含了每一行的row ID, row ID隨著新行的插入而單調(diào)增加。然后在這個(gè)隱藏列上建立索引作為clustered index。

    Secondary Index:除了Clustered Index之外的索引都是Secondary Index,每一個(gè)Secondary Index的記錄中除了索引列的值之外,還包含主健值。通過(guò)二級(jí)索引查詢首先查到是主鍵值,然后InnoDB再根據(jù)查到的主鍵值通過(guò)主鍵/聚簇索引找到相應(yīng)的數(shù)據(jù)塊。

字段類型

  • 盡量使用數(shù)字型字段
    若只含數(shù)值信息的字段盡量不要設(shè)計(jì)為字符型,這會(huì)降低查詢和連接的性能,并會(huì)增加存儲(chǔ)開銷。
    因?yàn)橐嬖谔幚聿樵兒瓦B接時(shí)會(huì)逐個(gè)比較字符串中每一個(gè)字符,而對(duì)于數(shù)字型而言只需要比較一次就夠了。
    比如,我們的表很多是用字符串來(lái)做主鍵或連接字段,這里其實(shí)可以用字符串作為業(yè)務(wù)主鍵,但使用自增id做主鍵和連接字段;
  • 盡可能的使用 varchar/nvarchar(指定長(zhǎng)度) 代替 char/nchar
    首先變長(zhǎng)字段存儲(chǔ)空間小,可以節(jié)省存儲(chǔ)空間;
    其次對(duì)于查詢來(lái)說(shuō),在一個(gè)相對(duì)較小的字段內(nèi)搜索效率顯然要高些。
  • 對(duì)于少數(shù)枚舉值的字段使用 ENUM 而不是 VARCHAR
    枚舉類型,限定值的取值范圍,比如性別(男,女,未知)等。
    ENUM 類型是非常快和緊湊的,其保存的是 TINYINT,但外表上顯示為字符串。這樣一來(lái),用這個(gè)字段來(lái)做一些選項(xiàng)列表變得相當(dāng)?shù)耐昝馈?/p>

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

    注意:不推薦在mysql中設(shè)置某一字段類型為enum,但是存的值為數(shù)字,比如‘0’,‘1’,‘2’;

    表結(jié)構(gòu)優(yōu)化建議

    select column from table_name procedure analyse();

表連接時(shí)的注意事項(xiàng)

  • 盡量用 inner join
    避免 LEFT JOINNULL;
  • 盡量將條件寫到on中,而不是都寫到where
    onwhere的執(zhí)行順序:
    ON條件(A LEFT JOIN B ON條件表達(dá)式中的ON)用來(lái)決定如何從 B 表中檢索數(shù)據(jù)行。
    僅在匹配階段完成以后,WHERE子句條件才會(huì)被使用,它將從匹配階段產(chǎn)生的數(shù)據(jù)中檢索過(guò)濾。
    所以在使用連接時(shí),尤其是 left join(或right join)時(shí),一定要在先給出盡可能多的匹配滿足條件,以減少需要匹配的數(shù)據(jù)量,并減少Where的執(zhí)行。

    關(guān)于連接的用法參考:http://www.cnblogs.com/BeginM...

其他注意事項(xiàng)

  • 任何地方都不要使用 select * from t ,而應(yīng)用具體的字段。
  • 盡量使用表變量來(lái)代替臨時(shí)表。
    如果表變量包含大量數(shù)據(jù),請(qǐng)注意索引非常有限(只有主鍵索引)。
  • 避免頻繁創(chuàng)建和刪除臨時(shí)表,以減少系統(tǒng)表資源的消耗。
  • 在新建臨時(shí)表時(shí),如果一次性插入數(shù)據(jù)量很大,那么可以使用 select into 代替 create table,避免造成大量 log ,以提高速度;如果數(shù)據(jù)量不大,為了緩和系統(tǒng)表的資源,應(yīng)先create table,然后insert。
  • 如果使用到了臨時(shí)表,在存儲(chǔ)過(guò)程的最后務(wù)必將所有的臨時(shí)表顯式刪除,先 truncate table ,然后 drop table ,這樣可以避免系統(tǒng)表的較長(zhǎng)時(shí)間鎖定。
  • 盡量避免向客戶端返回大數(shù)據(jù)量,若數(shù)據(jù)量過(guò)大,應(yīng)該考慮相應(yīng)需求是否合理。
  • 千萬(wàn)不要 ORDER BY RAND()。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多

    精品香蕉一区二区在线| 深夜福利亚洲高清性感| 国产日韩综合一区在线观看| 久久热中文字幕在线视频| 国产免费观看一区二区| 色婷婷日本视频在线观看| 国产美女精品人人做人人爽| 国产欧美一区二区另类精品| 午夜福利直播在线视频| 日韩成人动画在线观看| 草草夜色精品国产噜噜竹菊 | 黄色片一区二区在线观看| 久久热九九这里只有精品| 中文字幕在线五月婷婷| 中文字幕欧美视频二区| 久久综合日韩精品免费观看| 午夜日韩在线观看视频| 日本不卡视频在线观看| 中文字幕无线码一区欧美| 欧美一区二区三区播放| 果冻传媒精选麻豆白晶晶 | 欧美美女视频在线免费看| 亚洲男女性生活免费视频| 五月婷日韩中文字幕四虎| 有坂深雪中文字幕亚洲中文| 国产又色又爽又黄又大| 亚洲一区二区三区在线免费| 国产精品美女午夜福利| 少妇人妻一级片一区二区三区| 国产人妻熟女高跟丝袜| 国产精品免费精品一区二区| 国产香蕉国产精品偷在线观看| 成年女人午夜在线视频| 99久久国产亚洲综合精品| 暴力性生活在线免费视频| 国自产拍偷拍福利精品图片| 国产又粗又爽又猛又黄的| 麻豆果冻传媒一二三区| 在线免费国产一区二区三区| 99久久免费看国产精品| 日本成人中文字幕一区|