SQL優(yōu)化學習

一、學習框架

mysql常見問題

image
  1. 一條查詢語句的執(zhí)行過程:一條語句在客戶端執(zhí)行,通過連接器跟服務(wù)器建立起連接跪者,通過連接器控制連接的數(shù)量蛀序,獲知客戶端的狀態(tài)川抡,為每一個客戶端建立起TCP連接拴事。然后到詞法分析器践剂,進行詞法分析和語法分析溉知,詞法分析將語句解析成一個個token詞陨瘩,語法分析將token詞生成語法樹。優(yōu)化器負責生成執(zhí)行計劃级乍,選擇索引舌劳。根據(jù)優(yōu)化器選擇的索引,執(zhí)行器調(diào)用存儲引擎的接口取數(shù)據(jù)玫荣,執(zhí)行語句甚淡。

重點:優(yōu)化器如何選擇索引?

  • 掃描行數(shù):掃描行數(shù)怎么判斷捅厂?一個索引上不同的值的個數(shù)贯卦,我們稱之為“基數(shù)”(cardinality)。也就是說焙贷,這個基數(shù)越大撵割,索引的區(qū)分度越好 。MySQL是通過采樣統(tǒng)計的方式來判斷的辙芍。但是掃描行數(shù)只是個預(yù)估值啡彬,存在對mysql誤導的情況
  • 是否使用臨時表 --見下方關(guān)于排序的講解
  • 是否需要排序
  1. 索引:索引需要知道索引的結(jié)構(gòu),聚集索引和非聚集索引的區(qū)別故硅,普通索引和唯一索引的區(qū)別庶灿,什么時候適合用普通索引,普通索引能夠用上change buffer的優(yōu)化

  2. 覆蓋索引&回表:如果需要查詢的字段吃衅,都包含在索引里面(通常是聯(lián)合索引)往踢,那么就不需要去主鍵索引回表,因為只有主鍵索引的葉子結(jié)點包含row數(shù)據(jù)行徘层,這也是一種常見的優(yōu)化手段峻呕。
    需要注意的是回表掃描的行數(shù)不會體現(xiàn)在rows_examed里,因為rows_examed是表示執(zhí)行引擎從存儲器取了多少次數(shù)據(jù)惑灵,而是否回表是取決于不同的存儲引擎山上,例如innoDb需要回表,myslam就不需要回表
    如果有聯(lián)合主鍵索引(a,b)英支,和索引c佩憾,a,c,ac,abc都可以走索引

  3. 索引下推:索引下推的前提是有覆蓋索引,通過索引下推,在覆蓋索引遍歷的時候?qū)⒁恍┎环系男羞^濾掉妄帘,減少回表的次數(shù)楞黄。

無索引下推:

image

有索引下推:

image
  1. 排序---總結(jié),如果排序字段有索引抡驼,能夠自然有序鬼廓,
  • rowid排序
  • 全字段排序
  • 內(nèi)排序
  • 外排序
  1. 慢查詢
  • 開啟:slow_query_log 慢查詢開啟狀態(tài),long_query_time 查詢超過多少秒才記錄
  • 參數(shù)

在有些場景下致盟,執(zhí)行器調(diào)用一次碎税,在引擎內(nèi)部則掃描了多行,因此引擎掃描行數(shù)跟 rows_examined 并不是完全相同的

image
  1. explain語句
  • 通沉笪看 possible_keys 以及 key 兩個字段

  • possible_keys 的內(nèi)容取決于 where 語句 + EXPLAIN TABLE 的結(jié)果雷蹂,即 where 會用到哪些 EXPLAIN TABLE 中能看到的索引

  • key 表示 MySQL 存儲引擎實際選擇的索引。這個索引可能不是 possible_keys 中列出來的

  • key_len 表示實際使用的索引的長度杯道,通常能根據(jù)這個字段 + key 來判斷用了 key 的哪幾個字段

當前表的關(guān)聯(lián)方式匪煌,也對查詢性能影響較大。對應(yīng)的在 EXPLAIN 結(jié)果中党巾,有個 type 字段來參考關(guān)聯(lián)方式萎庭。通常問題 SQL 中會出現(xiàn) type=ALL 或者 type=index 的情況,即全表掃描齿拂。下面列舉了下 type 的可能值驳规,按照性能從好到差來排序。

  • system & const: 表示你條件可以被轉(zhuǎn)換為常數(shù)列(即能通過條件確定唯一值)署海,比如

  • 只有一行記錄的系統(tǒng)表:system

  • where 條件是 pk or unique key 的唯一值达舒,例如 a=1 & a is pk or uk

  • eq_ref & ref & ref_or_null

  • eq_ref:previous table 的內(nèi)容能在當前 table 唯一確認一列

  • ref:用了索引,但是做不到 eq_ref 那么好叹侄,就是 ref

  • ref_or_null:等價 ref,比 ref 多比較了一個 null 的情況

  • fulltext:使用了 FULLTEXT 索引

    • index_merge
  • 采用了多個索引昨登,此時 key 列會展示用到的具體索引

  • unique_subquery & index_subquery

  • 針對 IN 類型的 subquery 優(yōu)化

  • range

  • 用了索引趾代,判斷采用范圍讀取的方式比較好

  • 通常會出現(xiàn)在范圍類型的 operator & 當前索引中用到的列,其區(qū)分度比較小的情況

  • range 對 column 相關(guān) operator 是有要求的丰辣,支持的有:=, <>, >, >=, <, <=, IS NULL, <=>, BETWEEN, or IN()

  • index & all

  • 都是全表掃描撒强,區(qū)別是用非主鍵還是主鍵

  • 要注意的是,不同索引的掃描笙什,數(shù)據(jù)的返回順序是不一樣的

  • rows:預(yù)估掃描行

二飘哨、排查思路

  1. 索引使用不符合預(yù)期
  • 沒有用索引---選擇合適的索引

  • 優(yōu)化器選擇了錯誤索引---優(yōu)化器為什么會選錯索引呢?force_index或者使用order by 引導優(yōu)化器使用合適的索引

  • 索引沒有實現(xiàn)覆蓋索引---根據(jù)業(yè)務(wù)決定如何用上覆蓋索引的優(yōu)化

  1. 掃描行數(shù)過多---limit m,n 跳過m行取n行琐凭,會出現(xiàn)掃描m+n的結(jié)果
  2. IO存在問題芽隆,獲取不到連接,或者被無效的連接占有
  3. 返回不需要的列,慎用select * 尤其是一些字段是json胚吁,如果使用select *會造成IO壓力

三牙躺、分析慢查詢的思路

  1. explain查看情況
  2. 分析語句的執(zhí)行計劃和執(zhí)行過程
  3. 結(jié)合業(yè)務(wù)尋找優(yōu)化點

SQL優(yōu)化---while true 并且limit m,n導致的SQL掃描行數(shù)過多。limit m,n會取出m+n行數(shù)據(jù)腕扶,然后跳過m行孽拷,因此rows_examed會是m+n。

image
SELECT id, uid2, accepted, frm, crtime, uptime FROM contact_request WHERE (uid=110977129) AND (type=1) AND (frm!='addrbook_multi') AND (crtime>'2000-01-01 00:00:00') ORDER BY crtime desc LIMIT 0,1001

def get_exclude_talent_ids_add_fr(manager, uid, start):
    to_uids = []
    ht = {}
    page = 0
    size = 1000
    while True:
        cr_rows = network_service.get_cttreq_all_addfr_requests(manager=manager, uid=uid, crtime=start,
                                                                page=page * size, count=size + 1)
        remain = 0
        if cr_rows:
            if len(cr_rows) > size:
                remain = 1
            for cr_row in cr_rows:
                to_uid = cr_row['uid2']
                if to_uid not in ht:
                    to_uids.append(to_uid)
                    ht[to_uid] = to_uid
        if remain:
            page += 1
        else:
            break
    return to_uids

Limit m,n-->id>max_fid limit n

explain SELECT count(*)  FROM contact_request WHERE (uid=110977129) AND (type=1) AND (frm!='addrbook_multi') AND (crtime>'2000-01-01 00:00:00') and id>max_id ORDER BY crtime desc LIMIT 1001

def get_exclude_talent_ids_add_fr_new(manager, uid, start):
    to_uids = []
    ht = {}
    size = 1000
    max_id = 0
    while True:
        cr_rows = network_service.get_cttreq_addfr_requests_by_crtime(manager=manager, uid=uid, crtime=start, limit=size+1, id=max_id)
        remain = 1 if len(cr_rows) > size else 0
        if cr_rows:
            start = cr_rows[len(cr_rows) - 1]['crtime']-datetime.timedelta(seconds=1)
            max_id = cr_rows[len(cr_rows) - 1]['id']
            for cr_row in cr_rows:
                to_uid = cr_row['uid2']
                if to_uid not in ht:
                    to_uids.append(to_uid)
                    ht[to_uid] = to_uid
        if not remain:
            break
    return to_uids

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末半抱,一起剝皮案震驚了整個濱河市脓恕,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌窿侈,老刑警劉巖炼幔,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異棉磨,居然都是意外死亡江掩,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進店門乘瓤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來环形,“玉大人,你說我怎么就攤上這事衙傀√б鳎” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵统抬,是天一觀的道長火本。 經(jīng)常有香客問我,道長聪建,這世上最難降的妖魔是什么钙畔? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮金麸,結(jié)果婚禮上擎析,老公的妹妹穿的比我還像新娘。我一直安慰自己挥下,他們只是感情好揍魂,可當我...
    茶點故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著棚瘟,像睡著了一般现斋。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上偎蘸,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天庄蹋,我揣著相機與錄音瞬内,去河邊找鬼。 笑死蔓肯,一個胖子當著我的面吹牛遂鹊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播蔗包,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼秉扑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了调限?” 一聲冷哼從身側(cè)響起舟陆,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎耻矮,沒想到半個月后秦躯,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡裆装,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年踱承,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片哨免。...
    茶點故事閱讀 39,731評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡茎活,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出琢唾,到底是詐尸還是另有隱情载荔,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布采桃,位于F島的核電站懒熙,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏普办。R本人自食惡果不足惜工扎,卻給世界環(huán)境...
    茶點故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望衔蹲。 院中可真熱鬧定庵,春花似錦、人聲如沸踪危。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贞远。三九已至,卻和暖如春笨忌,著一層夾襖步出監(jiān)牢的瞬間蓝仲,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留袱结,地道東北人亮隙。 一個月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像垢夹,于是被迫代替她去往敵國和親溢吻。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容