High Performance MySQL 筆錄(schema/index 部分)
1.uuid用binary保存
建議uuid不要使用char來保存,而用binary(16)來保存。這里在長度上來講用binary會節(jié)省一半。因為一個字符占用1個字節(jié),而一個字節(jié)實際上可以表示0-256(2^8),用16進制的表示需要2個字節(jié)00-FF(0-256)。
優(yōu)化前:SET uuid =
UUID() (類型:char(36))
優(yōu)化后:SET uuid =
HEX(REPLACE(UUID(), '-', '')) (類型:binary(16))
筆記:這個東西主要是節(jié)省一下空間可以嘗試試著用一下哦!
2.用crc32替換長字符串的查找
如果索引列是個很長的字符串,例如url。那可以再建立一個列用來保存這個列的crc32結果,以提高索引的使用速度。
優(yōu)化前:WHERE url
= 'http://willko./' (索引:url,類型:var/char(?))
優(yōu)化后:WHERE
url_crc32 = CRC32('http://willko./') AND url =
'http://willko./' (索引:url_crc32,類型:unsigned int)
示例:
select
crc32('http://www.google.cn') from server;
打印的是115600293 就是其做了crc32運算之后的結果了!
筆記與心得:如果以后我們要對一個大的文本類型的字段創(chuàng)建索引的話呢。我們可以再加進來一個字段做冗余處理這個字段的內容保存的為CRC32 的結果值。主要目的是為了用到索引
3.前綴索引和后綴索引
前綴索引聽得比較多,優(yōu)點是減少索引的長度,缺點是排序不能使用前綴索引(影響distinct/order/group),也不會出現Covering Index(只讀取索引就能滿足查詢)。
后綴索引還是首次聽到,孤陋寡聞了。因為MySQL不支持反向索引,所有有時候查詢會有問題,例如字段blog保存用戶的博客地址
(http://willko.),那需要查詢某個域名有多少個用戶就不好查詢,可以用一個額外的字段反轉保存。 blog_reverse:moc.eyeavaj.willko://ptth,這樣就很容易查到(moc.eyeavaj)有 多少用戶了,并可以使用索引,也就是解決了 LIKE '%?'的問題,因為查詢反轉成LIKE '?%'了。
4.散列數據
散列數據就是把原本只有一條記錄的散列成多條,充分利用InnoDB行鎖的特性,提高并發(fā)。
例如,之前是UPDATE
hit_counter SET cnt = cnt + 1 WHERE id = ?
散列后是 UPDATE
hit_counter SET cnt = cnt + 1 WHERE id = ? AND slot = rand() * 100
散列后查詢需要合并數據。
筆記與心得:innodb是行鎖。所以啊它在處理這種大的并發(fā)的時候是非常高效的。哦因為是行鎖并發(fā)性能要高。所以在大的論壇的時候是用innodb哦!
另外我在有一篇文章里面有一個東西介紹統計count(*) 在處理統計innodb的時候很慢然后我新建一個表單獨存放其總量。然后再做了一次散列原因就是為了提高并發(fā)處理能力
5.優(yōu)化limit和offset
MySQL的limit工作原理就是先讀取n條記錄,然后拋棄前n條,讀m條想要的,所以n越大,性能會越差。
優(yōu)化前SQL: SELECT
* FROM member ORDER BY last_active LIMIT 50,5
優(yōu)化后SQL: SELECT
* FROM member INNER JOIN (SELECT member_id FROM member ORDER BY last_active
LIMIT 50, 5) USING (member_id)
分別在于,優(yōu)化前的SQL需要更多I/O浪費,因為先讀索引,再讀數據,然后拋棄無需的行。而優(yōu)化后的SQL(子查詢那條)只讀索引(Cover index)就可以了,然后通過member_id讀取需要的列。
筆記:這個我得要好好借鑒一下了。因為現在的表如果有超過近千萬條記錄的話。
SELECT * FROM member ORDER BY last_active LIMIT 50,5
讀取的順序是:
1、
先讀索引(前提是你得創(chuàng)建索引
如member_id這個索引)
2、
再讀數據(依據索引再讀取數據這個是MSYQL優(yōu)化器做的工作)
3、
然后因為limit
的原理是先讀取n條記錄再拋棄前n條所以這里面我們得將無需的數據丟棄掉。這樣的話其實我們是浪費了大量的IO操作。
優(yōu)化后的SQL:
SELECT * FROM member INNER JOIN (SELECT member_id FROM
member ORDER BY last_active LIMIT 50, 5) USING (member_id)
子查詢雖然被人罵但用得好還是比較爽的。這里面我們就使用了子查詢來提高查詢性能
1、
讀索引SELECT
member_id FROM member ORDER BY last_active LIMIT 50, 5
這個跟第一個語句做的工作其實是一樣的。
2、
依據索引讀所要的數據(只讀5條我們要的數據)
完成!
看到沒有 優(yōu)化之后的SQL語句不需要先把前面的全部數據提取出來,然后再丟棄不要的數據。而是依據索引直接定位。速度非???!大大地減少了IO
學到了三招?。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。?/span>
|