qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

          MySQL數(shù)據(jù)庫性能優(yōu)化之SQL優(yōu)化

          這篇文章是以 MySQL 為背景,很多內(nèi)容同時適用于其他關(guān)系型數(shù)據(jù)庫,需要有一些索引知識為基礎(chǔ)。

            優(yōu)化目標(biāo)

            1、減少 IO 次數(shù)

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

            2、降低 CPU 計算

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

            優(yōu)化方法

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

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

            常見誤區(qū)

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

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

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

            這個誤區(qū)甚至在很多的資深工程師或者是 DBA 中都普遍存在,很多人都會認(rèn)為這是理所當(dāng)然的。實際上,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ù)量其實是一樣的。

            當(dāng)然,也有例外情況,那就是我們的這個查詢在索引中就可以完成,也就是說當(dāng)只取 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)化手段

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

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

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

          posted on 2012-04-20 09:35 順其自然EVO 閱讀(375) 評論(0)  編輯  收藏 所屬分類: 數(shù)據(jù)庫

          <2012年4月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 泽普县| 桦川县| 通州区| 榆林市| 朝阳区| 延川县| 濮阳市| 昌平区| 盐城市| 济宁市| 万宁市| 兴海县| 阳高县| 塔河县| 远安县| 石棉县| 雷州市| 汝城县| 梓潼县| 舞钢市| 永修县| 元氏县| 屏山县| 长丰县| 沁源县| 通海县| 阳西县| 阿荣旗| 赤壁市| 临汾市| 冷水江市| 鄂尔多斯市| 客服| 丹东市| 于都县| 剑河县| 博客| 绩溪县| 浦县| 白朗县| 洪雅县|