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