日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL 慢查询优化

發(fā)布時間:2025/4/14 数据库 17 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL 慢查询优化 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

為什么查詢速度會慢

  1.慢是指一個查詢的響應時間長。一個查詢的過程:

  • 客戶端發(fā)送一條查詢給服務器
  • 服務器端先檢查查詢緩存,如果命中了緩存,則立可返回存儲在緩存中的結(jié)果。否則進入下一個階段
  • 服務器端進行SQL解析、預處理,再由優(yōu)化器生成對應的執(zhí)行計劃。
  • MySQL根據(jù)優(yōu)化器生成的執(zhí)行計劃,調(diào)用存儲引擎的API來執(zhí)行查詢。
  • 將結(jié)果返回給客戶端

  2.數(shù)據(jù)訪問

  • 是否向數(shù)據(jù)庫請求了不需要的數(shù)據(jù)
  • 是否掃描額外的記錄

  3.查詢的方式

  • 一個復雜的查詢還是多個簡單的查詢
  • 切分查詢(將大查詢切分成小查詢,循環(huán)完成小查詢)
  • 分解關聯(lián)查詢

慢查詢分析

  問題SQL

    把復雜的SQL分成多個簡單SQL并執(zhí)行,查看具體那個字段會慢,區(qū)分度不高。

  EXPLAIN

    顯示SQL如何使用索引的執(zhí)行計劃。

    執(zhí)行計劃的參數(shù):

table?顯示這一行的數(shù)據(jù)是關于哪張表的

type?顯示連接使用了何種類型。從最好到最差的連接類型為const、eq_reg、ref、range、indexhe和ALL

possible_keys?顯示可能應用在這張表中的索引。如果為空,沒有可能的索引。可以為相關的域從WHERE語句中選擇一個合適的語句?

key?實際使用的索引。如果為NULL,則沒有使用索引。很少的情況下,MYSQL會選擇優(yōu)化不足的索引。這種情況下,可以在SELECT語句中使用USE INDEX(indexname)來強制使用一個索引或者用IGNORE INDEX(indexname)來強制MYSQL忽略索引?

key_len??使用的索引的長度。在不損失精確性的情況下,長度越短越好?

ref?顯示索引的哪一列被使用了,如果可能的話,是一個常數(shù)

rows?掃描請求數(shù)據(jù)的行數(shù)?

Extra?關于MYSQL如何解析查詢的額外信息

  PROFILE

    顯示SQL執(zhí)行消耗系統(tǒng)資源的信息。

查詢執(zhí)行的過程

MySQL客戶端/服務器通信協(xié)議是“半雙工”的??头?服務器端都可以向?qū)Ψ桨l(fā)送數(shù)據(jù),但不能同時發(fā)生。所以我們無法也無須將一個消息切成小塊獨立來發(fā)送。

這種協(xié)議沒辦法進行流量控制。

客戶端發(fā)送請求的數(shù)據(jù)包大小由參數(shù)max_allowed_packet限制。如果查詢太大,服務端會拒絕接受更多的數(shù)據(jù)并拋出相應的錯誤。

服務器端返回的多個數(shù)據(jù)包,客戶端必須完整接受。

  1.查詢狀態(tài) SHOW FULL PROCESSLIST      

mysql>SHOW FULL PROCESSLIST;Id User Host db Command Time State Info ------ ------ --------------- ------------ ------- ------ ------ -----------------------1 root localhost:61316 laravel_blog Query 0 (NULL) show FULL processlist 2 root localhost:61319 (NULL) Sleep 94 (NULL)

?    對于一個連接,或者說一個線程,任何時刻都有一個狀態(tài),該狀態(tài)表示了MySQL當前正在做什么。

?

  2.查詢緩存  

-- 查看緩存是否開啟?(query_cache_type 為 ON 表示已經(jīng)開啟
mysql> show variables like '%query_cache%';

+------------------------------+----------+ | Variable_name | Value | +------------------------------+----------+ | have_query_cache | YES | | query_cache_limit | 1048576 | | query_cache_min_res_unit | 4096 | | query_cache_size | 20971520 | | query_cache_type | ON | | query_cache_wlock_invalidate | OFF | +------------------------------+----------+

    檢查sql是否命中緩存。命中則檢查一次用戶權(quán)限后返回,這個檢查是通過一個對大小寫敏感的哈希查找實現(xiàn)的。兩次查詢只要有一個字節(jié)的不同就會失敗。否則將進入下一個階段。

    當sql中有不確定的數(shù)據(jù)時,則不會被緩存。例如用戶自定義函數(shù)、存儲函數(shù)、用戶變量、臨時表、mysql庫中的系統(tǒng)表,其查詢結(jié)果都不會被緩存。

  

 3.查詢優(yōu)化

    語法解析器和預處理

      MySQL通過關鍵字將sql語句進行解析,并生成一顆對應的解析樹。這個過程解析器主要通過語法規(guī)則來驗證和解析。比如sql中是否使用了錯誤的關鍵字或者關鍵字的順序是否正確等。預處理則會根據(jù)MySQL規(guī)則進一步檢查解析樹是否合法。比如檢查要查詢的數(shù)據(jù)表和數(shù)據(jù)列是否存在等。

    查詢優(yōu)化器

      經(jīng)過前面的步驟生成的語法樹被認為是合法的了,并且由優(yōu)化器將其轉(zhuǎn)化成查詢計劃。多數(shù)情況下,一條查詢可以有很多種執(zhí)行方式,最后都返回相應的結(jié)果。優(yōu)化器的作用就是找到這其中最好的執(zhí)行計劃。

      MySQL使用基于成本的優(yōu)化器,通過計算成本選擇其中最小的一個。通過SHOW STATUS LIKE 'Last_query_cost';查看成本。成本的最小單位是隨機讀取一個4K數(shù)據(jù)頁的成本。

      MySQL的查詢優(yōu)化器是一個非常復雜的部件,它使用了非常多的優(yōu)化策略來生成一個最優(yōu)的執(zhí)行計劃:

      • 重新定義關聯(lián)表的順序
      • 將外連接轉(zhuǎn)化成內(nèi)連接
      • 使用等價變換規(guī)則
      • 優(yōu)化count()、min()、max()
      • 預估并轉(zhuǎn)化為常數(shù)表達式
      • 覆蓋索引描述
      • 子查詢優(yōu)化
      • 提前終止查詢
      • 等值傳播
      • 列表IN()的比較    

      上面列舉了一些,隨著MySQL的不斷發(fā)展,優(yōu)化器使用的優(yōu)化策略也在不斷的進化?!?/p>

    查詢執(zhí)行引擎

      在完成解析和優(yōu)化階段以后,MySQL會生成對應的執(zhí)行計劃,查詢執(zhí)行引擎根據(jù)執(zhí)行計劃給出的指令逐步執(zhí)行得出結(jié)果。整個執(zhí)行過程的大部分操作均是通過調(diào)用存儲引擎實現(xiàn)的接口來完成,這些接口被稱為handler API。查詢過程中的每一張表由一個handler實例表示。實際上,MySQL在查詢優(yōu)化階段就為每一張表創(chuàng)建了一個handler實例,優(yōu)化器可以根據(jù)這些實例的接口來獲取表的相關信息,包括表的所有列名、索引統(tǒng)計信息等。存儲引擎接口提供了非常豐富的功能,但其底層僅有幾十個接口,這些接口像搭積木一樣完成了一次查詢的大部分操作。

    返回結(jié)果

      查詢執(zhí)行的最后一個階段就是將結(jié)果返回給客戶端。即使查詢不到數(shù)據(jù),MySQL仍然會返回這個查詢的相關信息,比如該查詢影響到的行數(shù)以及執(zhí)行時間等。

      如果查詢緩存被打開且這個查詢可以被緩存,MySQL也會將結(jié)果存放到緩存中。

      結(jié)果集返回客戶端是一個增量且逐步返回的過程。有可能MySQL在生成第一條結(jié)果時,就開始向客戶端逐步返回結(jié)果集了。這樣服務端就無須存儲太多結(jié)果而消耗過多內(nèi)存,也可以讓客戶端第一時間獲得返回結(jié)果。需要注意的是,結(jié)果集中的每一行都會以一個滿足①中所描述的通信協(xié)議的數(shù)據(jù)包發(fā)送,再通過TCP協(xié)議進行傳輸,在傳輸過程中,可能對MySQL的數(shù)據(jù)包進行緩存然后批量發(fā)送。

?

性能優(yōu)化

  優(yōu)化count()查詢

    count()是一個特殊的函數(shù)。可以統(tǒng)計行數(shù)、某個列值的數(shù)量。在統(tǒng)計列值時要求列值是非空的(不統(tǒng)計NULL)。在統(tǒng)計行數(shù)時count(*)不會被擴展成所有的列,而是忽略所有的列。這樣寫意義清晰,性能好。

    • 在不要求完全精確時,EXPLAIN返回一個優(yōu)化器估算的近似值
    • 快速,精確和實現(xiàn)簡單,三者永遠只能滿足其二,必須舍掉其中一個。增加一個匯總表也是

  

  優(yōu)化LIMIT分頁

    LIMIT 10000,20這樣的查詢,MySQL需要查詢10020條記錄后返回最后20記錄。一般優(yōu)化為WHERE id>10000 LIMIT 20。其他優(yōu)化關聯(lián)一個冗余表,冗余表只包含主鍵列和需要排序的數(shù)據(jù)列。

  

  數(shù)據(jù)類型優(yōu)化

    選擇數(shù)據(jù)類型的原則:更小的通常更好、簡單就好、盡量避免NULL。

    更小的數(shù)據(jù)類型通常會更快,因為占用更少的磁盤、內(nèi)存和CPU緩存。

    簡單的數(shù)據(jù)類型需要更少的CPU周期。例:int比char的操作代價低。

  這里總結(jié)幾個可能容易理解錯誤的技巧:

  • 通常來說把可為NULL的列改為NOT NULL不會對性能提升有多少幫助,只是如果計劃在列上創(chuàng)建索引,就應該將該列設置為NOT NULL。

  • 對整數(shù)類型指定寬度,比如INT(11),沒有任何卵用。INT使用32位(4個字節(jié))存儲空間,那么它的表示范圍已經(jīng)確定,所以INT(1)和INT(20)對于存儲和計算是相同的。

  • UNSIGNED表示不允許負值,大致可以使正數(shù)的上限提高一倍。比如TINYINT存儲范圍是-128 ~ 127,而UNSIGNED TINYINT存儲的范圍卻是0 - 255。

  • 通常來講,沒有太大的必要使用DECIMAL數(shù)據(jù)類型。即使是在需要存儲財務數(shù)據(jù)時,仍然可以使用BIGINT。比如需要精確到萬分之一,那么可以將數(shù)據(jù)乘以一百萬然后使用BIGINT存儲。這樣可以避免浮點數(shù)計算不準確和DECIMAL精確計算代價高的問題。

  • TIMESTAMP使用4個字節(jié)存儲空間,DATETIME使用8個字節(jié)存儲空間。因而,TIMESTAMP只能表示1970 - 2038年,比DATETIME表示的范圍小得多,而且TIMESTAMP的值因時區(qū)不同而不同。

  • 大多數(shù)情況下沒有使用枚舉類型的必要,其中一個缺點是枚舉的字符串列表是固定的,添加和刪除字符串(枚舉選項)必須使用ALTER TABLE(如果只只是在列表末尾追加元素,不需要重建表)。

  • schema的列不要太多。原因是存儲引擎的API工作時需要在服務器層和存儲引擎層之間通過行緩沖格式拷貝數(shù)據(jù),然后在服務器層將緩沖內(nèi)容解碼成各個列,這個轉(zhuǎn)換過程的代價是非常高的。如果列太多而實際使用的列又很少的話,有可能會導致CPU占用過高。

  • 大表ALTER TABLE非常耗時,MySQL執(zhí)行大部分修改表結(jié)果操作的方法是用新的結(jié)構(gòu)創(chuàng)建一個張空表,從舊表中查出所有的數(shù)據(jù)插入新表,然后再刪除舊表。尤其當內(nèi)存不足而表又很大,而且還有很大索引的情況下,耗時更久。當然有一些奇技淫巧可以解決這個問題,有興趣可自行查閱。

  • ?  索引的設計

        索引的優(yōu)點:大大減少了服務器需要掃描的數(shù)據(jù)量、幫主服務器避免排序和臨時表、可以將隨機I/O變?yōu)轫樞騃/O;

    “三星系統(tǒng)”:索引將相關的記錄放到一起則獲得一星;如果索引中的數(shù)據(jù)順序和查找中的排序順序一致則獲得二星;如果索引中的列包含了查詢中需要的全部列則獲得三星。

      • 獨立的列:索引列不能是表達式的一部分,也不能是函數(shù)的參數(shù)。索引選擇區(qū)分度高。
      • 前綴索引:如果列很長,通常索引開始的部分字符,可以大大節(jié)約索引空間,從而提高索引效率。
      • 聯(lián)合索引:當多個索引and時,通常是一個包含所有相關列的索引好過多個單獨索引;當多個索引or時,通常是分開查詢好過單次查詢。

    ?    注:如果在EXPLAIN中看到有索引合并(Extra字段出現(xiàn)Using union),應該好好檢查一下查詢和表的結(jié)構(gòu),看是不是已經(jīng)是最優(yōu)的。

    ?

    參考資料

      Baron Scbwartz 等著;寧海元 周振興等譯;高性能MySQL(第三版); 電子工業(yè)出版社, 2013

      

    轉(zhuǎn)載于:https://www.cnblogs.com/zhoutianyuan/p/11060483.html

    總結(jié)

    以上是生活随笔為你收集整理的MySQL 慢查询优化的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 亚洲精品电影在线观看 | 亚洲欧洲一区二区三区 | 亚洲区小说区 | 美日韩一区二区 | 日韩av不卡在线观看 | 在线一二区 | 亚洲区在线 | 久久中文字幕在线观看 | 国产成人免费观看 | 中文字幕一区二区三区乱码在线 | 欧美放荡办公室videos4k | 天天看夜夜爽 | 人成网站在线观看 | 日韩精品一区在线 | 在线免费h | 性史性dvd影片农村毛片 | 超碰超碰 | av中文资源网| 中文字幕日本一区 | 视频一区国产 | 男女搞网站 | 中文字幕亚洲天堂 | 中文字幕在线2018 | 久操视频免费看 | 日韩成人一级 | 国产肉体xxxx裸体784大胆 | 波多野结衣在线观看一区 | 香蕉视频影院 | 日韩视频网址 | 91你懂的 | 亚洲精品久久久久久久蜜桃 | 亚洲国产精品999 | 欧美黄网站在线观看 | 久久精品中文 | 国产91综合一区在线观看 | 亚洲免费久久 | 国产天天操| 伊人国产在线视频 | 动漫精品一区一码二码三码四码 | 天堂一区在线观看 | 国产伦精品一区二区三区视频网站 | 欧美色图一区二区三区 | 亚洲AV无码成人精品区明星换面 | 综合网婷婷 | 日本裸体网站 | 国 产 黄 色 大 片 | 456av| 欧美 亚洲 激情 一区 | 又黄又爽的免费视频 | 强公把我次次高潮hd | 久久阁| 国产精品久久久久久久久久妞妞 | 精品一区二区三区视频 | 国产日产欧美一区二区三区 | 97人妻精品一区二区三区 | 国产特级片 | 亚洲熟伦熟女新五十路熟妇 | 99爱国产 | 国产理论视频在线观看 | 在线播放国产视频 | 欧日韩在线观看 | 精品三级av | 特淫毛片 | 做暧暧视频在线观看 | 黄色av导航| 欧美日韩爱爱 | 天天做夜夜爱 | 亚洲精品视频播放 | 亚洲无码精品免费 | 欧美一本在线 | 红桃视频隐藏入口 | 欧美岛国国产 | 成人短视频在线 | 成人免费高清在线播放 | 天堂а在线中文在线新版 | 欧美在线视频免费播放 | 天堂色在线 | 国产精品23p| 欧美视频91 | 久久久久亚洲AV成人网人人小说 | 中文字幕在线日韩 | 福利91| 日本免费视频 | 日本中文字幕在线观看 | 亚洲性精品 | 污污网址在线观看 | 亚洲另类色综合网站 | 青娱乐国产视频 | 无码国产伦一区二区三区视频 | 国产偷人妻精品一区二区在线 | 日日夜夜艹 | 伊人激情影院 | 天堂国产精品 | 亚洲欧洲日本国产 | 国产污视频网站 | 国产老肥熟 | 人av在线| 九九午夜| 久草黄色 |