MySQL效能優化的最佳21條經驗(下)

2021-06-17 01:16:05 字數 3794 閱讀 9236

11. 盡可能的使用 not null

除非你有乙個很特別的原因去使用 null 值,你應該總是讓你的字段保持 not null。這看起來好像有點爭議,請往下看。

首先,問問你自己「empty」和「null」有多大的區別(如果是int,那就是0和null)?如果你覺得它們之間沒有什麼區別,那麼你就不要使用null。(你知道嗎?在 oracle 裡,null 和 empty 的字串是一樣的!)

不要以為 null 不需要空間,其需要額外的空間,並且,在你進行比較的時候,你的程式會更複雜。 當然,這裡並不是說你就不能使用null了,現實情況是很複雜的,依然會有些情況下,你需要使用null值。

12. prepared statements

prepared statements很像儲存過程,是一種執行在後台的sql語句集合,我們可以從使用 prepared statements 獲得很多好處,無論是效能問題還是安全問題。

prepared statements 可以檢查一些你繫結好的變數,這樣可以保護你的程式不會受到「sql注入式」攻擊。當然,你也可以手動地檢查你的這些變數,然而,手動的檢查容易出問題,而且很經常會被程式設計師忘了。當我們使用一些framework或是orm的時候,這樣的問題會好一些。

在效能方面,當乙個相同的查詢被使用多次的時候,這會為你帶來可觀的效能優勢。你可以給這些prepared statements定義一些引數,而mysql只會解析一次。

雖然最新版本的mysql在傳輸prepared statements是使用二進位制形勢,所以這會使得網路傳輸非常有效率。

當然,也有一些情況下,我們需要避免使用prepared statements,因為其不支援查詢快取。但據說版本5.1後支援了。

在php中要使用prepared statements,你可以檢視其使用手冊:mysqli 擴充套件 或是使用資料庫抽象層,如:pdo.

// 建立 prepared statement

if ($stmt = $mysqli->prepare("select username from user where state=?")) ') where user_id = $user_id";

15. 固定長度的表會更快

如果表中的所有欄位都是「固定長度」的,整個表會被認為是 「static」 或 「fixed-length」。 例如,表中沒有如下型別的字段: varchar,text,blob。只要你包括了其中乙個這些字段,那麼這個表就不是「固定長度靜態表」了,這樣,mysql 引擎會用另一種方法來處理。

固定長度的表會提高效能,因為mysql搜尋得會更快一些,因為這些固定的長度是很容易計算下乙個資料的偏移量的,所以讀取的自然也會很快。而如果字段不是定長的,那麼,每一次要找下一條的話,需要程式找到主鍵。

並且,固定長度的表也更容易被快取和重建。不過,唯一的***是,固定長度的字段會浪費一些空間,因為定長的字段無論你用不用,他都是要分配那麼多的空間。

使用「垂直分割」技術(見下一條),你可以分割你的表成為兩個乙個是定長的,乙個則是不定長的。

16. 垂直分割

「垂直分割」是一種把資料庫中的表按列變成幾張表的方法,這樣可以降低表的複雜度和字段的數目,從而達到優化的目的。(以前,在銀行做過專案,見過一張表有100多個字段,很恐怖)

示例一:在users表中有乙個欄位是家庭位址,這個欄位是可選字段,相比起,而且你在資料庫操作的時候除了個人資訊外,你並不需要經常讀取或是改寫這個字段。那麼,為什麼不把他放到另外一張表中呢? 這樣會讓你的表有更好的效能,大家想想是不是,大量的時候,我對於使用者表來說,只有使用者id,使用者名稱,口令,使用者角色等會被經常使用。小一點的表總是會有好的效能。

示例二: 你有乙個叫 「last_login」 的字段,它會在每次使用者登入時被更新。但是,每次更新時會導致該錶的查詢快取被清空。所以,你可以把這個字段放到另乙個表中,這樣就不會影響你對使用者id,使用者名稱,使用者角色的不停地讀取了,因為查詢快取會幫你增加很多效能。

另外,你需要注意的是,這些被分出去的字段所形成的表,你不會經常性地去join他們,不然的話,這樣的效能會比不分割時還要差,而且,會是極數級的下降。

17. 拆分大的 delete 或 insert 語句

apache 會有很多的子程序或執行緒。所以,其工作起來相當有效率,而我們的伺服器也不希望有太多的子程序,執行緒和資料庫鏈結,這是極大的佔伺服器資源的事情,尤其是記憶體。

如果你把你的表鎖上一段時間,比如30秒鐘,那麼對於乙個有很高訪問量的站點來說,這30秒所積累的訪問程序/執行緒,資料庫鏈結,開啟的檔案數,可能不僅僅會讓你泊web服務crash,還可能會讓你的整台伺服器馬上掛了。

while (1)

// 每次都要休息一會兒

usleep(50000); }

18. 越小的列會越快

對於大多數的資料庫引擎來說,硬碟操作可能是最重大的瓶頸。所以,把你的資料變得緊湊會對這種情況非常有幫助,因為這減少了對硬碟的訪問。

參看 mysql 的文件 storage requirements 檢視所有的資料型別。

如果乙個表只會有幾列罷了(比如說字典表,配置表),那麼,我們就沒有理由使用 int 來做主鍵,使用 mediumint, smallint 或是更小的 tinyint 會更經濟一些。如果你不需要記錄時間,使用 date 要比 datetime 好得多。

當然,你也需要留夠足夠的擴充套件空間,不然,你日後來幹這個事,你會死的很難看,參看slashdot的例子(2023年11月06日),乙個簡單的alter table語句花了3個多小時,因為裡面有一千六百萬條資料。

19. 選擇正確的儲存引擎

在 mysql 中有兩個儲存引擎 myisam 和 innodb,每個引擎都有利有弊。酷殼以前文章《mysql: innodb 還是 myisam?》討論和這個事情。

myisam 適合於一些需要大量查詢的應用,但其對於有大量寫操作並不是很好。甚至你只是需要update乙個字段,整個表都會被鎖起來,而別的程序,就算是讀程序都無法操作直到讀操作完成。另外,myisam 對於 select count(*) 這類的計算是超快無比的。

innodb 的趨勢會是乙個非常複雜的儲存引擎,對於一些小的應用,它會比 myisam 還慢。他是它支援「行鎖」 ,於是在寫操作比較多的時候,會更優秀。並且,他還支援更多的高階應用,比如:事務。

下面是mysql的手冊

target=」_blank」myisam storage engine

innodb storage engine

orm 的最重要的是「lazy loading」,也就是說,只有在需要的去取值的時候才會去真正的去做。但你也需要小心這種機制的***,因為這很有可能會因為要去建立很多很多小的查詢反而會降低效能。

orm 還可以把你的sql語句打包成乙個事務,這會比單獨執行他們快得多得多。

目前,個人最喜歡的php的orm是:doctrine。

21. 小心「永久鏈結」

「永久鏈結」的目的是用來減少重新建立mysql鏈結的次數。當乙個鏈結被建立了,它會永遠處在連線的狀態,就算是資料庫操作已經結束了。而且,自從我們的apache開始重用它的子程序後——也就是說,下一次的http請求會重用apache的子程序,並重用相同的 mysql 鏈結。

php手冊:mysql_pconnect()

而且,apache 執行在極端並行的環境中,會建立很多很多的了程序。這就是為什麼這種「永久鏈結」的機制工作地不好的原因。在你決定要使用「永久鏈結」之前,你需要好好地考慮一下你的整個系統的架構。 

MySQL效能優化的21條最佳經驗

多數的mysql伺服器都開啟了查詢快取。這是提高性最有效的方法之一,而且這是被mysql的資料庫引擎處理的。當有很多相同的查詢被執行了多次的時候,這些查詢結果會被放到乙個快取中,這樣,後續的相同的查詢就不用操作表而直接訪問快取結果了。今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於web應...

MySQL效能優化的21個最佳實踐

今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於web應用尤其明顯。關於資料庫的效能,這並不只是dba才需要擔心的事,而這更是我們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對運算元據庫時 尤其是查表時的sql 具體可以參考 inet aton和inet ntoa 15.固定長度...

MySQL效能優化的最佳20 條經驗

今天,資料庫的操作越來越成為整個應用的效能瓶頸了,這點對於web應用尤其明顯。關於資料庫的效能,這並不只是dba才需要擔心的事,而這更是我 們程式設計師需要去關注的事情。當我們去設計資料庫表結構,對運算元據庫時 尤其是查表時的sql語句 我們都需要注意資料操作的效能。這裡,我們不會講過 多的sql語...