国产高清在线免费观看-国产高清在线免费无码-国产高清在线男人的天堂-国产高清在线视频-国产高清在线视频精品视频-国产高清在线视频伊甸园

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

MySQL數(shù)據(jù)庫優(yōu)化的一些筆記,如何處理百萬行記錄

Ccoffee
2012年5月16日 11:54 本文熱度 3378
0. 索引很重要

  之前列舉記錄用了下面的語句。state字段為索引。


  SELECT * FROM feed_urls WHERE state='ok' AND feed_url<>'' LIMIT N,10


  當(dāng)記錄數(shù)量很大時(shí),有幾萬之后,這句SQL就很慢了。主要是因?yàn)閒eed_url沒有建立索引。后來的解決方法是,把feed_url為空的,設(shè)為一個(gè)ok以外的state值,就行了。


  1. 索引不是萬能的


  為了計(jì)算記錄總數(shù),下面的語句會(huì)很慢。


 


  mysql> SELECT COUNT(*) FROM feed_urls WHERE state='error';


  +----------+


  | COUNT(*) |


  +----------+


  | 30715 |


  +----------+


  1 row in set (0.14 sec)


  mysql> EXPLAIN SELECT COUNT(*) FROM feed_urls WHERE state='error'\G


  *************************** 1. row ***************************


  id: 1


  select_type: SIMPLE


  table: feed_urls


  type: ref


  possible_keys: state,page_index


  key: page_index


  key_len: 10


  ref: const


  rows: 25936


  Extra: Using where; Using index


  1 row in set (0.00 sec)


 


  state為索引,請(qǐng)求用時(shí)140ms。遍歷了state='error'索引下的每一條記錄。


 


  mysql> SELECT state,COUNT(*) FROM feed_urls GROUP BY state;


  +----------+----------+


  | state | COUNT(*) |


  +----------+----------+


  | error | 30717 |


  | fetching | 8 |


  | nofeed | 76461 |


  | ok | 74703 |


  | queued | 249681 |


  +----------+----------+


  5 rows in set (0.55 sec)


  mysql> EXPLAIN SELECT state,COUNT(*) FROM feed_urls GROUP BY state\G


  *************************** 1. row ***************************


  id: 1


  select_type: SIMPLE


  table: feed_urls


  type: index


  possible_keys: NULL


  key: state


  key_len: 10


  ref: NULL


  rows: 431618


  Extra: Using index


  1 row in set (0.00 sec)


 


  請(qǐng)求用時(shí)550ms。遍歷了每個(gè)state下的每一條記錄。


  改進(jìn)方法:


  獨(dú)立一個(gè)表用來計(jì)數(shù),使用MySQL的Trigger同步計(jì)數(shù):


 


  CREATE TRIGGER my_trigger AFTER UPDATE ON feed_urls


  FOR EACH ROW BEGIN


  IF OLD.state <> NEW.state THEN


  IF NEW.state='ok' THEN


  UPDATE feed_stat SET count_feed = count_feed + 1;


  END IF;


  IF NEW.state IN ('ok', 'error', 'nofeed') THEN


  UPDATE feed_stat SET count_access = count_access + 1;


  END IF;


  END IF;


  END


 


  2. 當(dāng)分頁很大時(shí)


 


  mysql> SELECT * FROM feed_urls LIMIT 230000, 1\G


  *************************** 1. row ***************************


  id: 736841f82abb0bc87ccfec7c0fdbd09c30b5a24d


  link: http://mappemunde.typepad.com/


  title: Tim Peterson


  feed_url: NULL


  update_time: 2012-05-12 11:01:56


  state: queued


  http_server: NULL


  abstract: NULL


  previous_id: ceea30e0ba609b69198c53ce71c44070d69038c5


  ref_count: 1


  error: NULL


  aid: 230001


  1 row in set (0.50 sec)


  mysql> EXPLAIN SELECT * FROM feed_urls LIMIT 230000, 1\G


  *************************** 1. row ***************************


  id: 1


  select_type: SIMPLE


  table: feed_urls


  type: ALL


  possible_keys: NULL


  key: NULL


  key_len: NULL


  ref: NULL


  rows: 431751


  Extra:


  1 row in set (0.00 sec)


 


  讀取一條記錄,耗時(shí)500ms,因?yàn)楸碛涗浭亲冮L(zhǎng)的,所以MySQL不能算出目標(biāo)位置,只能每一條記錄的數(shù)過去。


  改進(jìn)方法:


  通過索引定位,數(shù)索引比數(shù)記錄要快,因?yàn)樗饕加玫目臻g比整條記錄小很多。


 


  mysql> SELECT * FROM (SELECT aid FROM feed_urls ORDER BY aid LIMIT 215000, 1) d JOIN feed_urls u ON d.aid=u.aid\G


  *************************** 1. row ***************************


  aid: 215001


  id: 2e4b1a385c8aae40b3ec2af9153805ca446f2029


  link: http://ncse.com/


  title: NCSE


  feed_url: NULL


  update_time: 2012-05-12 10:47:15


  state: queued


  http_server: NULL


  abstract: NULL


  previous_id: 819a6e3c5edc1624a9b8f171d8d3ae269843785f


  ref_count: 3


  error: NULL


  aid: 215001


  1 row in set (0.06 sec)


  mysql> EXPLAIN SELECT * FROM (SELECT aid FROM feed_urls ORDER BY aid LIMIT 215000, 1) d JOIN feed_urls u ON d.aid=u.aid\G


  *************************** 1. row ***************************


  id: 1


  select_type: PRIMARY


  table:


  type: system


  possible_keys: NULL


  key: NULL


  key_len: NULL


  ref: NULL


  rows: 1


  Extra:


  *************************** 2. row ***************************


  id: 1


  select_type: PRIMARY


  table: u


  type: const


  possible_keys: aid


  key: aid


  key_len: 4


  ref: const


  rows: 1


  Extra:


  *************************** 3. row ***************************


  id: 2


  select_type: DERIVED


  table: feed_urls


  type: index


  possible_keys: NULL


  key: aid


  key_len: 4


  ref: NULL


  rows: 211001


  Extra: Using index


  3 rows in set (0.15 sec)


 


  耗時(shí)60ms,比之前的方法快了將近10倍。如果LIMIT語句里還有WHERE a=1,應(yīng)該建立一個(gè)(a,aid)的索引。


  話說,MySQL好像還是不能直接算出第21500條索引的位置呀,這種方法還是數(shù)了索引了,能算出來就直接0ms了。不過這樣的效率,對(duì)于百萬級(jí)的,還能應(yīng)付吧。如果是千萬級(jí)的或者像我之前在KS創(chuàng)建的一張上億條記錄的表(120G),這種方法就肯定不行了。


  經(jīng)過上述優(yōu)化,打開最后一頁的速度已經(jīng)很快了(之前需要800ms,現(xiàn)在則為300ms左右)。


\

  膜拜下這Burst.NET最低檔次的VPS (30RMB/month)。


  root@xiaoxia-pc:~/# ping feed.readself.com -n


  PING app.readself.com (184.82.185.32) 56(84) bytes of data.


  64 bytes from 184.82.185.32: icmp_req=1 ttl=45 time=161 ms


  64 bytes from 184.82.185.32: icmp_req=2 ttl=45 time=161 ms


  64 bytes from 184.82.185.32: icmp_req=3 ttl=45 time=161 ms


  用同樣的方法,優(yōu)化了搜索引擎的排名算法。即排名過程中選取盡量少的值出來排序,排序后再JOIN一次獲取結(jié)果的信息。


  排序過程如下:


 


  SELECT u.*, count_level(u.id) lv


  FROM(


  SELECT f.id, f.ref_count, MATCH(i.link,i.title) AGAINST (keywords) score


  FROM feed_index i


  JOIN feed_urls f ON f.id=i.id


  WHERE MATCH(i.link,i.title) AGAINST (keywords)


  ORDER BY score*0.5 + score*0.5*(ref_count/max_ref_count_in_result) DESC


  LIMIT offset,10


  ) d JOIN feed_urls u ON u.id = d.id


 


  目前處理10萬記錄的全文索引數(shù)據(jù),MySQL還是可以滿足的,就是不知道上百萬之后,還能不能撐下去。撐不下去就依賴第三方的工具了,例如Sphinx


  3. SELECT里的函數(shù)


  給FeedDB增加了層次的顯示。因?yàn)楸救颂珣校詻]有給數(shù)據(jù)庫表增加一個(gè)記錄深度的字段。所以,直接寫了一個(gè)MySQL的自定義函數(shù) count_level,用來統(tǒng)計(jì)通過parent_id一直找到頂層經(jīng)過的路徑長(zhǎng)度(Level)。


 


  CREATE DEFINER=`feeddb_rw`@`%` FUNCTION `count_level`(fid char(40)) RETURNS int(11)


  BEGIN


  SET @levels = 0;


  SET @found = false;


  WHILE NOT @found DO


  SELECT previous_id INTO @prev_id FROM feed_urls WHERE id=fid;


  IF @prev_id is null OR @prev_id = '' THEN


  SET @found = true;


  ELSE


  SET @levels = @levels + 1;


  SET fid = @prev_id;


  END IF;


  END WHILE;


  IF @prev_id is null THEN


  RETURN null;


  END IF;


  RETURN @levels;


  END


 


  在網(wǎng)頁顯示的時(shí)候用了類似下面的SQL語句。


 


  mysql> SELECT u.*, count_level(u.id) FROM feed_urls u ORDER BY ref_count DESC LIMIT 12000,1\G


  *************************** 1. row ***************************


  id: e42f44b04dabbb9789ccb4709278e881c54c28a3


  link: http://tetellita.blogspot.com/


  title: le hamburger et le croissant


  feed_url: http://www.blogger.com/feeds/7360650/posts/default


  update_time: 2012-05-15 14:50:53


  state: ok


  http_server: GSE


  abstract: Lepekmezest un épais sirop bordeaux obtenu par réduction dumoût de raisin, une sorte de mélasse de raisin, en somme. Légèrement acidulé, il apporte du pep's aux yaourts et nappe avec bonheur les


  previous_id: 129cabd96e7099a53b78c7ddeff98658351082e9


  ref_count: 9


  error: NULL


  aid: 174262


  count_level(u.id): 8


  1 row in set (4.10 sec)


 


  好吧,悲劇了!4100ms。一定對(duì)12000個(gè)條目都算了一次count_level,然后再進(jìn)行排序。所以才用上了4秒那么漫長(zhǎng)的時(shí)間!!!


  改進(jìn)方法:


  先SELECT LIMIT,再在派生的臨時(shí)表里,計(jì)算count_level。


 


  mysql> SELECT u.*, count_level(u.id) FROM (


  SELECT id FROM feed_urls ORDER BY ref_count DESC LIMIT 27521,1


  ) d JOIN feed_urls u ON u.id=d.id\G


  *************************** 1. row ***************************


  id: 61df288dda131ffd6125452d20ad0648f38abafd


  link: http://mynokiamobile.org/


  title: My Nokia Mobile


  feed_url: http://mynokiamobile.org/feed/


  update_time: 2012-05-14 14:06:57


  state: ok


  http_server: Apache/2.2.19 (Unix) mod_ssl/2.2.19 OpenSSL/1.0.0-fips mod_auth_passthrough/2.1 mod_bwlimited/1.4 FrontPage/5.0.2.2635


  abstract: ArchivesSelect MonthMay 2012April 2012March 2012February 2012January 2012December 2011November 2011October 2011September 2011August 2011July 2011June 2011May 2011April 2011March 2011February 2011Janua


  previous_id: f37af92bb89c08f6d4b69e72eab05d8ab1e2aca4


  ref_count: 5


  error: NULL


  aid: 154996


  count_level(u.id): 8


  1 row in set (0.09 sec)


 


  如此,優(yōu)化之后效果好很多了!但是還可以繼續(xù)優(yōu)化,例如建立一個(gè)字段存儲(chǔ)Level的值應(yīng)該是最好的辦法了。


  初次了解MySQL一些工作機(jī)制,歡迎一起探討!


該文章在 2012/5/16 11:54:16 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲(chǔ)管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved

主站蜘蛛池模板: 91久久综合九色综合 | 无码av中文一区二 | 亚洲精品国产乱码AV在线观看 | 国产69久久久欧美黑人A片 | 国产成人一区在线播放 | 亚洲精品久久无码AV片俺去也 | 亚洲永久免费看mv网站入口 | 四虎精品国产av二区 | 天美传媒国产今日推荐 | 亚洲精品久久久久一区二区 | 尤物在线观看在线播放 | 亚洲一区二区免费 | 国产69精品久久久久观看软件 | 日韩麻豆电影一区二区 | 亚州成在线人视屏观看 | 亚洲丁香色婷婷综合欲色啪 | 亚洲精品无码永久在线 | 亚洲一区二区三区无码中文A片 | 无码一区二区三区aⅴ免费 无码一区二区精品视频久久久 | 日韩一区二区三区北条麻妃 | 亚洲午夜久久久久久久久电影网 | 国产午夜福利短视频 | 国产91无毒不卡在线观看 | 日日夜夜操B | 精品人妻一区二区三区四区 | 91久久久亚洲综合久久88 | 丰满人妻一区二区三区视频 | 亚洲精品天堂在线观看 | 精品欧美一区二区精品久久免费 | 少妇高清精品毛片在线视频 | 日韩久久久免费播放 | 偷图自拍日韩视频 | 国产仑乱无码内谢 | 亚洲国产精品成人无码区 | 7799天天视频在线看 | 亚洲永久无码444kkk777 | 色情的人妻味道BD完整版 | 亚洲AⅤ中文无码字幕色 | 无码人妻少妇伦在线电影 | 亚洲精品中文字幕无码专区 | 香蕉久久av一区二区三区 |