1、數據類型優化mysql
數據類型
整數sql
數字類型:整數和實數數據庫
tinyint(8)、smallint(16)、mediuint(24)、int(32)、bigint(64) 數字表示對應最大存儲位數,如 tinyint (-127 --- 128),tinyint unsigned 表示不容許負數,則範圍爲 (0 -- 255)。編程
常規數據庫中 int(11) 只是表示控制顯示字符的個數是11個,int(1) 和 int(20) 存儲和計算是同樣的,即 int(1) 照樣能夠存儲1111(4位數)。緩存
實數數據結構
實數有分數部分架構
float 和 double 類型支持使用標準的浮點運算近似計算併發
float 佔用4個字節 double佔用8個字節app
decimal 類型用於保存精確的小數函數
decimal(18,9) 18表示小數點先後總位數 9表示小數點後面位數
mysql 5.0版本以上 4個字節保存9位數字
decimal(18,9) 共佔用9個字節 小數點前4個字節 小數點後佔1個 小數點後4個字節
字符串類型
varchar和char類型
varchar保存可變長度的字符串,比固定長度類型佔用更少的存儲空間,只佔用須要的空間。
varchar使用額外的1到2字節存儲長度,列小於255使用1字節保存長度,大於255使用2字節保存,varchar保留字符串末尾的空格。
char是固定長度,保存char值時候 **mysql去掉任何末尾的空格** ,進行比較時 空格會被填充到字符串末尾。
不少的char列,效率高於varchar,好比 char(1)對於單字節字符集佔用1字節,varchar(1)佔用兩字節,由於1字節保存長度。
慷慨不是明智的,分配真正須要的空間。
Blob和Text類型
blob和text惟一區別就是blob保存二進制數據、沒有字符集和排序規則。
選擇優化的數據類型
更小一般越好
使用更少的磁盤、內存、cpu,確保不會低估保存的值,可是text有字符集和排序規則。mysql不能索引這些數據類型的完整長度,也不能爲排序使用索引。
簡單就好
比較整數的代價小於比較字符,使用mysql內建類型保存時間和日期,使用整數保存ip。
儘可能避免NULL
mysql難以優化可空列查詢,使固定索引(整數列上的索引)編程可變大小索引;沒有值可使用 0 或者空字符串代替;把null 列改成not null 帶來的性能提高很小。
肯定類型
像數字、字符串、時間、直觀類型能夠肯定,可是像 datetime 和timestamp,能保存一樣的類型。timestamp使用空間只有datetime一半。能夠保存時區。
使用enum代替字符串類型
enum列能夠保存65535不一樣的字符串,存儲在一個 "查找表"中 mysql內部存儲的是列表中的位置。
內部存儲的是這個字符串對應的位置,實際表中存儲的仍是字符串。
建立一個表fruit category字段爲enum類型,包含4種不一樣水果:
插入4條數據,即4中不一樣水果。其中,最後一個菠蘿(pineapple) 沒有enum值 則插入了空數據。
發現字段category保存的仍是字符串,其實內部已經將這些字符串關聯到enum字符的位置。
支持字符串搜索和位置搜索
emu缺點在於插入數據以前,若是沒有對應enum,則須要alter表結構。
enum優勢在於佔用更少的存儲空間。
聽說 enum 用於聯接查詢性能也比較好。
日期和時間類型
datetime 保存是1001年到9999年,精度是秒,存儲值爲 2016-05-06 22:39:40。
timestamp保存自 1970年1月1日午夜以來的秒數,和unix時間戳相同,提供4字節存儲 只能表示1970年到2038年。默認timestamp值 爲 NOT NULL。
mysql中提供 from_unixtime()函數把unix時間戳轉換爲日期
unix_timestamp()把日期轉換爲unix時間戳
若是須要秒如下的精度保存日期和時間,可使用bigint類型把它以毫秒的精度保存時間戳格式,或使用double保存秒的分數部分。
選擇標識符
整數類型一般是標識符最佳選擇,速度快,且能使用auto_increment,避免使用字符串作標識符,佔用不少空間而且比整數類型要慢。
特殊類型的數據
一般使用varchar(15)保存IP地址,其實IP地址是無符號的32位整數,不是字符串,小數點僅僅爲了可讀性。
mysql提供了 inet_aton() inet_ntoa() ,用於 ip地址和整數以前轉換。
2、索引優化
索引基礎知識
索引幫助mysql高效獲取數據的數據結構,索引(mysql中叫"鍵(key)") 數據越大越重要。索引比如一本書,爲了找到書中特定的話題,查看目錄,得到頁碼。
select fruit_name from fruit where id = 5 索引列位於id列,索引按值查找而且返回任何包含該值的行。
若是索引了多列數據,那麼列的順序很是重要。
存儲引擎說明
myisam 存儲引擎
表鎖:myisam 表級鎖
不支持自動恢復數據:斷電以後 使用以前檢查和執行可能的修復
不支持事務:不保證單個命令會完成, 多行update 有錯誤 只有一些行會被更新
只有索引緩存在內存中:mysiam只緩存進程內部的索引
緊密存儲:行被僅僅保存在一塊兒
Innodb存儲引擎
事務性:Innodb支持事務和四種事務隔離級別
外鍵:Innodb惟一支持外鍵的存儲引擎 create table 命令接受外鍵
行級鎖:鎖設定於行一級 有很好的併發性
多版本:多版本併發控制
按照主鍵彙集:索引按照主鍵彙集
全部的索引包含主鍵列:索引按照主鍵引用行 若是不把主鍵維持很短 索引就增加很大
優化的緩存:Innodb把數據和內存緩存到緩衝池 自動構建哈希索引
未壓縮的索引:索引沒有使用前綴壓縮,阻塞auto_increment:Innodb使用表級鎖產生新的auto_increment
沒有緩存的count():myisam 會把行數保存在表中 Innodb中的count()會全表或索引掃描
索引在存儲引擎實現的,而不是服務層。
B-tree 索引
大多數談及的索引類型就是B-tree類型, 能夠在create table 和其餘命令使用它 myisam使用前綴壓縮以減少索引,Innodb不會壓縮索引,myiam索引按照行存儲物理位置引用被索引的行,Innodb按照主鍵值引用行,B-tree數據存儲是有序的,按照順序保存了索引的列,加速了數據訪問,存儲引擎不會掃描整個表獲得須要的數據。
B-tree 索引實例
使用B-tree索引的查詢類型,很好用於全鍵值、鍵值範圍或鍵前綴查找,只有在超找使用了索引的最左前綴的時候纔有用。
匹配全名:全鍵值匹配和索引中的全部列匹配
查找叫Tang Kang 出生於 1991-09-23 的人
匹配最左前綴:B-tree找到姓爲tang的人
匹配列前綴: 匹配某列的值的開頭部分 查找姓氏以T開頭的人
匹配範圍值:索引查找姓大於Tang小於zhu的人
精確匹配一部分而且匹配某個範圍的另一部分:
查找姓爲Tang而且名字以字母K開頭的人 精確匹配last_name列而且對
first_name進行範圍查詢
只訪問索引的查詢:B-tree支持只訪問索引的查詢,不會訪問行
B-tree侷限性
B-tree侷限性:(案例中索引順序:last_name first_name dob )
若是查找沒有送索引列的最左邊開始,沒有什麼用處,即不能查找全部叫Kang 的人,也不能找到全部出生在某天的人,由於這些列再也不索引最左邊,也不能使用該索引超找某個姓氏以特定字符結尾的人。
不能跳過索引的列,即不能找到全部姓氏爲Tang而且出生在某個特定日期的人,若是不定義first_name列的值,Mysql只能使用索引的第一列。
存儲引擎不能優化任何在第一個範圍條件右邊的列,好比查詢是where last_name = 'Tang' AND first_name like 'K%' AND dob='1993-09-23' 訪問只能使用索引頭兩列。
由此可知 索引列順序的重要性!
哈希索引
目前只有Memory存儲引擎支持顯示的哈希索引,並且Memory引擎對我來講不經常使用,因此咱們就輕描淡寫的過了吧。
R-tree(空間索引)
Myisam支持空間索引,可使用geometry空間數據類型。
空間索引不會要求where子句使用索引最左前綴能夠全方位索引數據,能夠高效使用任何數據組合查找 配合使用mercontains()函數使用。
全文索引
fulltext是Myisam表特殊索引,從文本中找關鍵字不是直接和索引中的值進行比較。
全文索引能夠和B-Tree索引混用,索引價值互不影響。
全文索引用於match against操做 而不是普通的where子句。
前綴索引和索引選擇性
一般索引幾個字符,而不是所有值,以節約空間並獲得好的性能,同時也下降選擇性。
索引選擇性是不重複的索引值和所有行數的比值。高選擇性的索引有好處,查找匹配過濾更多的行,惟一索引選擇率爲1最佳狀態。
blob列、text列及很長的varchar列,必須定義前綴索引,mysql不容許索引他們的全文。
前綴索引和索引選擇性實例
造數據
#複製一份與cs_area表結構
#插入1600數據
#模擬真實數據
#表area有name列 須要對name列前綴索引
#計算得比值接近0.9350就行了
#分別取 3 4 5位name值計算
#可知name列添加5位前綴索引就能夠了
#Mysql不能在order by 或 group by查詢使用前綴索引 也不能將其用做覆蓋索引
彙集索引
彙集索引不是一種單獨的索引類型,而是一種存儲數據的方式。
Innodb 的彙集索引實際上一樣的結構保存了B-tree索引和數據行,"彙集" 是指實際的數據行和相關的鍵值保存在一塊兒,每一個表只能有一個彙集索引,所以不能一次把行保存在兩個地方。 (因爲彙集索引對我來講不經常使用,咱們就略過啦~)
覆蓋索引
索引支持高效查找行,mysql也能使用索引來接收列的數據。這樣不用讀取行數據,當發起一個被索引覆蓋的查詢,explain解釋器的extra列看到 using index。
#知足條件:#
# select 查詢的字段必須 有索引全覆蓋
select last_name,first_name 其中 last_name 和first_name 必須都有索引
#不能在索引執行like操做
爲排序使用索引掃描
mysql排序結果的方式:使用文件排序 、 掃描有序的索引
explain中的type列若爲 "索引(Index)" 說明mysql掃描索引。單純掃描索引很快,若是mysql沒有使用索引覆蓋查詢 就不得不查找索引中發現的每一行。
mysql能有爲排序和查找行使用一樣的索引,如表 user 索引 (uid,birthday ) 。
使用排序索引:
避免多餘和重複索引
重複索引:類型相同,以一樣的順序在一樣的列建立索引,好比在表user id列 添加 unique(id)約束 、id not null。
primary key 約束 index(id),其實這些是相同的索引 !
多餘索引:如存在(A)索引 應該擴展它 知足 (A,B)索引
(A,B)索引 <==> (B)
(A,B)索引 <==> (A)
(A,B) A最左前綴 (B,A) B最左前綴
索引實例研究
支持多種過濾條件
不在選擇性不好的列添加索引
優化排序
索引和表維護
表維護三個目標:查找和修復損壞、維護精確的索引統計,並減小碎片
查找並修復表損壞
check table 命令:肯定表是否損壞,能抓到大部分表和索引錯誤
repair table 命令:修復損壞的表
myisamchk :離線修復工具
更新索引統計
analyze table cs_area 更新索引統計信息,便於優化器優化sql
show index 命令檢查索引的基數性
減小索引和數據碎片
正則化和非正則化
正則化和非正則化
正則化數據庫:每一個因素只會表達一次,教師表teacher (id,school_id), 學校表school
(school_id,school_name) 優勢:更新信息只變更一張表 缺點:簡單的學校名稱查詢 須要關聯表
非正則化數據庫:信息是重複的 或者 保存在多個地方
教師表teacher (id,school_id,school_name) 學校表school
(school_id,school_name)
優勢:便於直接統計對應學校名稱的老師
缺點:更新須要變更的表多一張
正則化和非正則化並用:好比須要統計用戶的發帖數 能夠在user表添加字段num_message 保存發帖總數 避免高密度查詢統計
緩存和彙總表
實例:統計過去24小時發佈的信息精確的數量
表週期性建立
週期建立能夠獲得沒有碎片和全排序索引的高效表
注意:此法會將數據清除,只是獲得一個沒有碎片和高效的索引表。
計數表:好比緩存用戶朋友數量、文件下載次數 一般創建一個單獨的表,以保持快速維護計數器。
計劃任務按期聚合函數查詢,更新對應的字段。