最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

揭秘SQL優(yōu)化技巧 改善數(shù)據(jù)庫性能

 更新時間:2012年01月30日 17:48:20   作者:  
這篇文章是以 MySQL 為背景,很多內(nèi)容同時適用于其他關(guān)系型數(shù)據(jù)庫,需要有一些索引知識為基礎(chǔ),重點講述如何優(yōu)化SQL,來提高數(shù)據(jù)庫的性能
優(yōu)化目標

  1、減少 IO 次數(shù)

  IO永遠是數(shù)據(jù)庫最容易瓶頸的地方,這是由數(shù)據(jù)庫的職責(zé)所決定的,大部分數(shù)據(jù)庫操作中超過90%的時間都是 IO 操作所占用的,減少 IO 次數(shù)是 SQL 優(yōu)化中需要第一優(yōu)先考慮,當然,也是收效最明顯的優(yōu)化手段。

  2、降低CPU計算

  除了 IO 瓶頸之外,SQL優(yōu)化中需要考慮的就是CPU運算量的優(yōu)化了。order by, group by,distinct … 都是消耗 CPU 的大戶(這些操作基本上都是 CPU 處理內(nèi)存中的數(shù)據(jù)比較運算)。當我們的 IO 優(yōu)化做到一定階段之后,降低 CPU 計算也就成為了我們 SQL 優(yōu)化的重要目標

  優(yōu)化方法

  1、改變 SQL 執(zhí)行計劃

  明確了優(yōu)化目標之后,我們需要確定達到我們目標的方法。對于 SQL 語句來說,達到上述2個目標的方法其實只有一個,那就是改變 SQL 的執(zhí)行計劃,讓他盡量“少走彎路”,盡量通過各種“捷徑”來找到我們需要的數(shù)據(jù),以達到 “減少 IO 次數(shù)” 和 “降低 CPU 計算” 的目標

  常見誤區(qū)

  1、count(1)和count(primary_key) 優(yōu)于 count(*)

  很多人為了統(tǒng)計記錄條數(shù),就使用 count(1) 和 count(primary_key) 而不是 count(*) ,他們認為這樣性能更好,其實這是一個誤區(qū)。對于有些場景,這樣做可能性能會更差,應(yīng)為數(shù)據(jù)庫對 count(*) 計數(shù)操作做了一些特別的優(yōu)化。

  2、count(column) 和 count(*) 是一樣的

  這個誤區(qū)甚至在很多的資深工程師或者是 DBA 中都普遍存在,很多人都會認為這是理所當然的。實際上,count(column) 和 count(*) 是一個完全不一樣的操作,所代表的意義也完全不一樣。

  count(column) 是表示結(jié)果集中有多少個column字段不為空的記錄

  count(*) 是表示整個結(jié)果集有多少條記錄

  3、select a,b from … 比 select a,b,c from … 可以讓數(shù)據(jù)庫訪問更少的數(shù)據(jù)量

  這個誤區(qū)主要存在于大量的開發(fā)人員中,主要原因是對數(shù)據(jù)庫的存儲原理不是太了解。

  實際上,大多數(shù)關(guān)系型數(shù)據(jù)庫都是按照行(row)的方式存儲,而數(shù)據(jù)存取操作都是以一個固定大小的IO單元(被稱作 block 或者 page)為單位,一般為4KB,8KB… 大多數(shù)時候,每個IO單元中存儲了多行,每行都是存儲了該行的所有字段(lob等特殊類型字段除外)。

  所以,我們是取一個字段還是多個字段,實際上數(shù)據(jù)庫在表中需要訪問的數(shù)據(jù)量其實是一樣的。

  當然,也有例外情況,那就是我們的這個查詢在索引中就可以完成,也就是說當只取 a,b兩個字段的時候,不需要回表,而c這個字段不在使用的索引中,需要回表取得其數(shù)據(jù)。在這樣的情況下,二者的IO量會有較大差異。

  4、order by 一定需要排序操作

  我們知道索引數(shù)據(jù)實際上是有序的,如果我們的需要的數(shù)據(jù)和某個索引的順序一致,而且我們的查詢又通過這個索引來執(zhí)行,那么數(shù)據(jù)庫一般會省略排序操作,而直接將數(shù)據(jù)返回,因為數(shù)據(jù)庫知道數(shù)據(jù)已經(jīng)滿足我們的排序需求了。

  實際上,利用索引來優(yōu)化有排序需求的 SQL,是一個非常重要的優(yōu)化手段

  延伸閱讀:MySQL ORDER BY 的實現(xiàn)分析 ,MySQL 中 GROUP BY 基本實現(xiàn)原理 以及 MySQL DISTINCT 的基本實現(xiàn)原理 這3篇文章中有更為深入的分析,尤其是第一篇

  5、執(zhí)行計劃中有 filesort 就會進行磁盤文件排序

  有這個誤區(qū)其實并不能怪我們,而是因為 MySQL 開發(fā)者在用詞方面的問題。filesort 是我們在使用 explain 命令查看一條 SQL 的執(zhí)行計劃的時候可能會看到在 “Extra” 一列顯示的信息。

  實際上,只要一條 SQL 語句需要進行排序操作,都會顯示“Using filesort”,這并不表示就會有文件排序操作。

  延伸閱讀:理解 MySQL Explain 命令輸出中的filesort,我在這里有更為詳細的介紹

  基本原則

  1、盡量少 join

  MySQL 的優(yōu)勢在于簡單,但這在某些方面其實也是其劣勢。MySQL 優(yōu)化器效率高,但是由于其統(tǒng)計信息的量有限,優(yōu)化器工作過程出現(xiàn)偏差的可能性也就更多。對于復(fù)雜的多表 Join,一方面由于其優(yōu)化器受限,再者在 Join 這方面所下的功夫還不夠,所以性能表現(xiàn)離 Oracle 等關(guān)系型數(shù)據(jù)庫前輩還是有一定距離。但如果是簡單的單表查詢,這一差距就會極小甚至在有些場景下要優(yōu)于這些數(shù)據(jù)庫前輩。

  2、盡量少排序

  排序操作會消耗較多的 CPU 資源,所以減少排序可以在緩存命中率高等 IO 能力足夠的場景下會較大影響 SQL 的響應(yīng)時間。

  對于MySQL來說,減少排序有多種辦法,比如:

  上面誤區(qū)中提到的通過利用索引來排序的方式進行優(yōu)化

  減少參與排序的記錄條數(shù)

  非必要不對數(shù)據(jù)進行排序

  …

  3、盡量避免 select *

  很多人看到這一點后覺得比較難理解,上面不是在誤區(qū)中剛剛說 select 子句中字段的多少并不會影響到讀取的數(shù)據(jù)嗎?

  是的,大多數(shù)時候并不會影響到 IO 量,但是當我們還存在 order by 操作的時候,select 子句中的字段多少會在很大程度上影響到我們的排序效率,這一點可以通過我之前一篇介紹 MySQL ORDER BY 的實現(xiàn)分析 的文章中有較為詳細的介紹。

  此外,上面誤區(qū)中不是也說了,只是大多數(shù)時候是不會影響到 IO 量,當我們的查詢結(jié)果僅僅只需要在索引中就能找到的時候,還是會極大減少 IO 量的。

  4、盡量用 join 代替子查詢

  雖然 Join 性能并不佳,但是和 MySQL 的子查詢比起來還是有非常大的性能優(yōu)勢。MySQL 的子查詢執(zhí)行計劃一直存在較大的問題,雖然這個問題已經(jīng)存在多年,但是到目前已經(jīng)發(fā)布的所有穩(wěn)定版本中都普遍存在,一直沒有太大改善。雖然官方也在很早就承認這一問題,并且承諾盡快解決,但是至少到目前為止我們還沒有看到哪一個版本較好的解決了這一問題。

  5、盡量少 or

  當 where 子句中存在多個條件以“或”并存的時候,MySQL 的優(yōu)化器并沒有很好的解決其執(zhí)行計劃優(yōu)化問題,再加上 MySQL 特有的 SQL 與 Storage 分層架構(gòu)方式,造成了其性能比較低下,很多時候使用 union all 或者是union(必要的時候)的方式來代替“or”會得到更好的效果。

  6、盡量用 union all 代替 union

  union 和 union all 的差異主要是前者需要將兩個(或者多個)結(jié)果集合并后再進行唯一性過濾操作,這就會涉及到排序,增加大量的 CPU 運算,加大資源消耗及延遲。所以當我們可以確認不可能出現(xiàn)重復(fù)結(jié)果集或者不在乎重復(fù)結(jié)果集的時候,盡量使用 union all 而不是 union。

  7、盡量早過濾

  這一優(yōu)化策略其實最常見于索引的優(yōu)化設(shè)計中(將過濾性更好的字段放得更靠前)。

  在 SQL 編寫中同樣可以使用這一原則來優(yōu)化一些 Join 的 SQL。比如我們在多個表進行分頁數(shù)據(jù)查詢的時候,我們最好是能夠在一個表上先過濾好數(shù)據(jù)分好頁,然后再用分好頁的結(jié)果集與另外的表 Join,這樣可以盡可能多的減少不必要的 IO 操作,大大節(jié)省 IO 操作所消耗的時間。

  8、避免類型轉(zhuǎn)換

  這里所說的“類型轉(zhuǎn)換”是指 where 子句中出現(xiàn) column 字段的類型和傳入的參數(shù)類型不一致的時候發(fā)生的類型轉(zhuǎn)換:

  人為在column_name 上通過轉(zhuǎn)換函數(shù)進行轉(zhuǎn)換

  直接導(dǎo)致 MySQL(實際上其他數(shù)據(jù)庫也會有同樣的問題)無法使用索引,如果非要轉(zhuǎn)換,應(yīng)該在傳入的參數(shù)上進行轉(zhuǎn)換

  由數(shù)據(jù)庫自己進行轉(zhuǎn)換

  如果我們傳入的數(shù)據(jù)類型和字段類型不一致,同時我們又沒有做任何類型轉(zhuǎn)換處理,MySQL 可能會自己對我們的數(shù)據(jù)進行類型轉(zhuǎn)換操作,也可能不進行處理而交由存儲引擎去處理,這樣一來,就會出現(xiàn)索引無法使用的情況而造成執(zhí)行計劃問題。

  9、優(yōu)先優(yōu)化高并發(fā)的 SQL,而不是執(zhí)行頻率低某些“大”SQL

  對于破壞性來說,高并發(fā)的 SQL 總是會比低頻率的來得大,因為高并發(fā)的 SQL 一旦出現(xiàn)問題,甚至不會給我們?nèi)魏未⒌臋C會就會將系統(tǒng)壓跨。而對于一些雖然需要消耗大量 IO 而且響應(yīng)很慢的 SQL,由于頻率低,即使遇到,最多就是讓整個系統(tǒng)響應(yīng)慢一點,但至少可能撐一會兒,讓我們有緩沖的機會。

  10、從全局出發(fā)優(yōu)化,而不是片面調(diào)整

  SQL 優(yōu)化不能是單獨針對某一個進行,而應(yīng)充分考慮系統(tǒng)中所有的 SQL,尤其是在通過調(diào)整索引優(yōu)化 SQL 的執(zhí)行計劃的時候,千萬不能顧此失彼,因小失大。

  11、盡可能對每一條運行在數(shù)據(jù)庫中的SQL進行 explain

  優(yōu)化 SQL,需要做到心中有數(shù),知道 SQL 的執(zhí)行計劃才能判斷是否有優(yōu)化余地,才能判斷是否存在執(zhí)行計劃問題。在對數(shù)據(jù)庫中運行的 SQL 進行了一段時間的優(yōu)化之后,很明顯的問題 SQL 可能已經(jīng)很少了,大多都需要去發(fā)掘,這時候就需要進行大量的 explain 操作收集執(zhí)行計劃,并判斷是否需要進行優(yōu)化。

  via IT168 技術(shù)

相關(guān)文章

  • MYSQL導(dǎo)入導(dǎo)出命令詳解

    MYSQL導(dǎo)入導(dǎo)出命令詳解

    網(wǎng)上看了一些總結(jié)出來的資料,不知道對大家有沒有用的,有用的話也就不枉費我一按按鈕的一片苦心了
    2007-09-09
  • MySQL如何從5.5升級到8.0(使用命令行升級)

    MySQL如何從5.5升級到8.0(使用命令行升級)

    最近為了解決mysql低版本的漏洞,這篇文章主要給大家介紹了關(guān)于MySQL如何從5.5升級到8.0的相關(guān)資料,主要使用的命令行升級,文中通過圖文介紹的非常詳細,需要的朋友可以參考下
    2023-03-03
  • 一文帶你探究MySQL中的NULL

    一文帶你探究MySQL中的NULL

    我們在日常工作中如果要接觸Mysql數(shù)據(jù)庫,那么不可避免會遇到Mysql中,下面這篇文章主要給大家介紹了關(guān)于MySQL中NULL的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下
    2021-11-11
  • mysql索引(覆蓋索引,聯(lián)合索引,索引下推)

    mysql索引(覆蓋索引,聯(lián)合索引,索引下推)

    這篇文章主要介紹了mysql索引(覆蓋索引,聯(lián)合索引,索引下推),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • MySQL入門教程(五)之表的創(chuàng)建、修改和刪除

    MySQL入門教程(五)之表的創(chuàng)建、修改和刪除

    MySQL 為關(guān)系型數(shù)據(jù)庫(Relational Database Management System), 本文給大家介紹MySQL入門教程(五)之表的創(chuàng)建、修改和刪除,需要的朋友一起學(xué)習(xí)吧
    2016-04-04
  • MySQL 5.7 版本的安裝及簡單使用(圖文教程)

    MySQL 5.7 版本的安裝及簡單使用(圖文教程)

    這篇文章主要介紹了MySQL 5.7 版本的安裝及簡單使用(圖文教程)的相關(guān)資料,這里對mysql 5.7的安裝及使用和注意事項,需要的朋友可以參考下
    2016-12-12
  • Mysql中索引和約束的示例語句

    Mysql中索引和約束的示例語句

    這篇文章主要介紹了Mysql中索引和約束的相關(guān)資料,幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下
    2021-01-01
  • MySQL批量導(dǎo)入Excel數(shù)據(jù)(超詳細)

    MySQL批量導(dǎo)入Excel數(shù)據(jù)(超詳細)

    這篇文章主要介紹了MySQL批量導(dǎo)入Excel數(shù)據(jù)(超詳細),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,感興趣的小伙伴可以參考一下,希望對你的學(xué)習(xí)有所幫助
    2022-08-08
  • MySQL存儲引擎簡介及MyISAM和InnoDB的區(qū)別

    MySQL存儲引擎簡介及MyISAM和InnoDB的區(qū)別

    這篇文章主要介紹了MySQL存儲引擎簡介及MyISAM和InnoDB的區(qū)別,重點介紹了MyISAM 和 InnoDB的區(qū)別,需要的朋友可以參考下
    2014-05-05
  • MySQL5.7的sql腳本導(dǎo)入到MySQL5.5出錯3種解決方案

    MySQL5.7的sql腳本導(dǎo)入到MySQL5.5出錯3種解決方案

    筆者需要將使用MySQL5.7數(shù)據(jù)庫的網(wǎng)站挪入winows服務(wù)器,目標服務(wù)器使用的是MySQL5.5,因為兼顧到以前的網(wǎng)站,MySQL不能升級。遇到MySQL5.7的sql腳本導(dǎo)入到MySQL5.5出錯,總結(jié)了3種解決方案,總有一個方案適合你。
    2023-06-06

最新評論

罗定市| 三江| 宝坻区| 邹平县| 长葛市| 金沙县| 自贡市| 阳新县| 灵璧县| 临海市| 板桥市| 景洪市| 长沙市| 鹰潭市| 饶河县| 平凉市| 郑州市| 读书| 射洪县| 霍山县| 玛沁县| 大邑县| 北宁市| 盐津县| 石城县| 莎车县| 宝山区| 九寨沟县| 仁化县| 成安县| 新津县| 冀州市| 措美县| 二手房| 长乐市| 玛曲县| 阳新县| 会理县| 和田县| 林西县| 长兴县|