程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 《高性能MySQL》讀書筆記(1),高性能mysql

《高性能MySQL》讀書筆記(1),高性能mysql

編輯:MySQL綜合教程

《高性能MySQL》讀書筆記(1),高性能mysql


慢查詢

當一個資源變得效率低下的時候,應該了解一下為什麼會這樣。有如下可能原因:
1.資源被過度使用,余量已經不足以正常工作。
2.資源沒有被正確配置
3.資源已經損壞或者失靈

因為慢查詢,太多查詢的實踐過長而導致堆積在邏輯上。
慢查詢到底是原因還是結果?在深入調查前是無法知曉的。記住,在正常的時候這個查詢也是正常運行的。一個查詢需要filesort和創建臨時表並不一定意味著就是有問題的。盡管消除filesort和臨時表通常來說是“最佳實踐”。

MySQL數據類型

一般情況下,應該盡量使用可以正確存儲數據的最小數據類型。更小的數據類型通常更快,因為它們占用更少的磁盤、內存和cpu緩存,並且處理時需要的cpu周期也更少。
簡單數據類型的操作通常需要更少的cpu周期,例如整型比字符操作代價耕地,因為字符集和校對規則(排序規則)使字符比較比整型比較更復雜,使用整型存儲IP地址。
盡量避免NULL,通常情況瞎最好制定列為NOT NULL,除非真的需要存儲NULL值。如果查詢中包含可為NULL的列,對mysql來說更難優化,因為可為NULL的列使得索引、索引統計和值比較都更復雜。

別名

MYSQL為了兼容性支持很多別名,例如integer、bool、numeric,他們都只是別名,雖然可能令人不解,但是不會影響性能。如果建表的時候采用數據類型的別名,然後用show create table檢查,會發現mysql報告的是基本類型,而不是別名。

MySQL可以為整數類型指定寬度,例如int(11),對大多數應用這是沒有意義的:它不會限制值的合法范圍,只是規定了mysql的一些交互工具(例如mysql命令行客戶端)用來顯示字符的個數。對於存儲和計算來說,int(1)和int(20)是相同的

字符類型

varchar類型選用於存儲可變長字符串,需要使用1或者2個額外字節記錄字符串的長度,比定長類型更節省空間,因為它僅使用必要的空間。
char類型是定長的:MySQL總是根據定義的字符串長度分配足夠的空間。
varchar的使用場景:
字符串列的最大長度比平均長度大很多;列的更新很少,所以碎片不是問題;使用了像utf-8這樣復雜的字符集,每個字符都使用不同的字節數進行存儲。
char適合於存儲很短的字符串,或者所有值都接近同一個長度。例如char非常適合存儲密碼MD5值,因為這是一個定長的值。對於經常變更的數據,char也比varchar更好,因為定長的char類型不容易產生碎片。

大字段字符類型

blob和text都是為了存儲很大的數據而設計的字符串數據類型,分別采用二進制和字符串方式存儲。MySQL對blob和text列進行排序於其他類型是不同的:它只對每個列的最前max_sort_length字節而不是整個字符串排序。
盡量避免使用text和blob類型,如果實在無法避免,有一個技巧實在所有用到blob字段的地方都是用substring(column,length)將列值轉換為字符串(在order by 子句中也適用),這樣就可以使用內存臨時表了。但是要確保截取的子字符串足夠短,不會使臨時表的大小超過max_heap_table_size或tmp_table_size,超過以後Mysql會將內存臨時表轉換為MyISAM磁盤臨時表。

時間類型

timestamp類型保存了從1970年1月1日午夜以來的秒數,timestamp只使用4個字節的存儲空間,因此它的范圍比datatime小得多:只能表示從1970年到2038年。提供了from_unixtime函數把unix時間戳轉換為日期、unix_timestamp函數把日期轉換為時間戳。
有時候人們會將unix時間戳存儲為整數值,這不會帶來任何收益。用整數保存時間戳的格式通常不方便處理,所以我們不推薦這麼做。

標識符(identifier)

整數通常是標識列最好的選擇,因為它們很快並且可以使用auto_increment;千萬不要使用enum和set類型作為標識列;盡量避免使用字符串類型作為標識列,因為他們很消耗空間,並且通常比數字類型慢。尤其是在MyISAM表裡使用字符串作為標識列時要特別小心,因為MyISAM默認對字符串使用壓縮索引,這會導致查詢慢得多。

IP地址字段

人們經常使用varchar(15)來存儲ip地址,然而,它們實際上是32位無符號整數,不是字符串。MySQL提供INET_ATON()和INET_NTOA()函數將ip地址在整數和四段表示形式之間進行轉換。

數據庫中的范式和反范式

在范式化的數據庫中,每個事實數據會出現並且只出現一次;相反,在反范式化的數據庫中,信息是冗余的,可能會存儲在多個地方。
范式化設計的schema的缺點是通常需要關聯,較多的關聯可能使得一些索引策略無效,例如,范式化可能將列存放在不同的表中,而這些列如果在一個表中本可以屬於同一個索引。
反范式的schema因為所有數據都在一張表中,可以很好地避免關聯。缺點是update操作的代價高,需要更新多個表,至於這會不會是一個問題,需要考慮更新的頻率以及更新的時長,並和執行select查詢的頻率進行比較
從另一個父表冗余一些數據到子表的理由通常是排序的需要。
緩存衍生值也是有用的。如果需要顯示每個用戶發了多少消息(像很多論壇做的),可以每次執行一個昂貴的子查詢來計算並顯示它;也可以在user表中建一個num_messages列,每當用戶發新消息時更新這個值。

緩存表和匯總表

緩存表和匯總表,實時計算統計值是非常昂貴的操作,因為要麼需要掃描表中的大部分數據,要麼查詢語句只能在某些特定的索引上才能有效運行,而這類特定索引一般會對update操作有影響,所以一般不希望創建這樣的索引。
使用緩存表和匯總表時,必須決定是實時維護數據還是定期重建,哪個更好依賴於應用程序,但是定期重建並不只是節省資源,也可以保持表不會有很多碎片,以及有完全順序組織的索引(這會更加高效)

計數器應用

如果應用在表中保存計數器,在更新計數器時可能會碰到並發問題。有一個技巧:將計數器保存在多行中,更新計數+1的操作改為隨機選擇一行進行更新,求計數值的時候,做一個sum求和。

表結構更改

一般而言,大部分alter table操作將導致MySQL服務中斷(鎖表並重建表)。MySQL執行大部分修改表結構的操作方法是用新的結構創建一個空表,從舊表中查出所有數據插入新表,然後刪除舊表。這昂操作可能需要花費很長時間。
不是所有的alter table操作都會引起表重建。理論上,MySQL可以跳過創建新表的步驟。列的默認值實際上存在表的.frm文件中,所以可以直接修改這個文件而不需要改動表本身。比如使用 alter comlum改變列的默認值:
alert table tablename
alert column col1 set default 5;
這個語句會直接修改.frm文件而不涉及表數據,所以這個操作是非常快的。

 

第四章以前

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved