MySQL 數(shù)據(jù)表優(yōu)化設(shè)計(八):如何設(shè)計統(tǒng)計數(shù)據(jù)表饱须?

有些時候域醇,改進數(shù)據(jù)表查詢性能的最佳方式是在同一張數(shù)據(jù)表中冗余一些繼承的數(shù)據(jù)。然而,有些時候需要新建完全獨立的統(tǒng)計或緩存數(shù)據(jù)表譬挚,尤其是在需要反復(fù)查詢的需求情況下锅铅。如果業(yè)務(wù)允許一些時間上的誤差的話,那么這種方式會更好减宣。

緩存型數(shù)據(jù)表通常在統(tǒng)計數(shù)據(jù)時會經(jīng)常用到盐须,因此也會叫統(tǒng)計性數(shù)據(jù)。舉個例子來說漆腌,對于員工贼邓、部門數(shù)據(jù)表而言,我們可能會需要查詢一個部門下有多少員工闷尿。這時候有三種方式實現(xiàn):

  • 在部門下增加一個員工數(shù)量的字段塑径,每次對員工進行增、改悠砚、刪操作時都需要同步更新員工數(shù)量(如果員工換部門晓勇,則需要更新多個部門的員工數(shù)量)。這種方式能夠保證實時性灌旧,但是卻很低效绑咱。對于如果是操作不頻繁時是沒問題的,假設(shè)相當頻繁枢泰,就意味著每次都需要操作兩張表描融,而且業(yè)務(wù)代碼都需要做埋點處理,將統(tǒng)計業(yè)務(wù)和普通業(yè)務(wù)深度耦合在一起了衡蚂。
  • 每次查詢的時候窿克,從員工表中執(zhí)行 SUM 函數(shù),獲取該部門的員工數(shù)毛甲。這種方式避免了埋點年叮,但是每次都需要去員工數(shù)據(jù)表求和,如果員工數(shù)據(jù)量大的話會很低效玻募。
  • 新建一張統(tǒng)計表只损,每隔一定時間從員工表中匯總每個部門的人員數(shù)量。這種定時抽取數(shù)據(jù)的方式會犧牲一定的實時性七咧,但降低了代碼的耦合跃惫,由于部門不會太多,這張表的大小是可預(yù)測的艾栋,也提高了數(shù)據(jù)訪問的效率爆存。這種方式即緩存型數(shù)據(jù)表

以手機端個人中心為例蝗砾,為展示每個用戶的關(guān)注人數(shù)先较、關(guān)注者和掘力值携冤,不可能每次查詢都去做一次 SUM,這意味著需要做多張表的 SUM 操作闲勺,效率會很低噪叙,而且掘力值的計算還涉及到更為復(fù)雜的計算方法(與文章的瀏覽量和點贊數(shù)有關(guān))。因此霉翔,可以猜測一下大致的表設(shè)計,這樣在查詢用戶個人主頁信息的時候只需要從這一張表就可以讀取到所有數(shù)據(jù)了苞笨。

CREATE t_user_summay (
  id INT PRIMARY KEY,
  user_id BIGINT(20),
  focused_user_cnt INT,
  followed_user_cnt INT,
  user_value INT,
  user_level ENUM('Lv1', 'Lv2', ..., 'Lv8'),
  created_time DATETIME,
  updated_time DATETIME,
);
image.png

是否需要實時更新

在實際應(yīng)用過程中债朵,統(tǒng)計表有兩種方式,一種是實時更新瀑凝,一種是周期性的重建數(shù)據(jù)序芦。兩種方式有利有弊,實時更新保證了查詢數(shù)據(jù)的即時性粤咪,但是會犧牲性能谚中,并且要求代碼埋點,而且由于數(shù)據(jù)更新是沒有規(guī)律的寥枝,可能產(chǎn)生碎片宪塔。周期性的重建數(shù)據(jù)犧牲了實時性,如果說大部分數(shù)據(jù)都不變的話會帶來不必要的統(tǒng)計計算囊拜,但如果數(shù)據(jù)經(jīng)常變動某筐,那周期性地重建數(shù)據(jù)顯然會更高效而且避免了埋點的情況。當然冠跷,避免應(yīng)用程序的埋點也可以通過觸發(fā)器來完成南誊,可以參考MySQL 高級特性(七):觸發(fā)器的正確打開方式

物化視圖工具(Flexviews)

在 MySQL 中蜜托,有一個 Flexviews 的開源工具用于從數(shù)據(jù)庫的binlog 中提取數(shù)據(jù)完成數(shù)據(jù)統(tǒng)計抄囚。有點類似與視圖,但與視圖所不同的是橄务,F(xiàn)lexviews 產(chǎn)生的數(shù)據(jù)表是物理表幔托,這也是為什么稱之為物化視圖的原因。而且仪糖,F(xiàn)lexviews 還支持增量更新和全量更新柑司。推薦使用增量更新,以避免所有行的統(tǒng)計數(shù)據(jù)都需要重建的情況锅劝。增量更新會檢查哪些數(shù)據(jù)行數(shù)據(jù)發(fā)生了改變攒驰,再執(zhí)行更新操作,相比全量更新而言性能會更高故爵。但為了檢測數(shù)據(jù)改變玻粪,需要引入一個視圖記錄數(shù)據(jù)行的變化日志隅津。

計數(shù)表

在實際開發(fā)中,我們經(jīng)常會需要對一些操作進行計數(shù)劲室,比如文章的閱讀數(shù)伦仍、點贊數(shù)。如果將計數(shù)值放入同一張表很可能在更新的時候出現(xiàn)并發(fā)問題很洋。使用獨立的計數(shù)表可以避免查詢緩存失效問題并使用一些更高級的技巧充蓝。例如統(tǒng)計文章的閱讀數(shù)、點贊數(shù)的數(shù)據(jù)表:

CREATE TABLE t_article_counter (
  article_id INT PRIMARY KEY,
  read_cnt INT UNSIGNED NOT NULL,
  praise_cnt INT UNSIGNED NOT NULL
);

在更新閱讀數(shù)的時候喉磁,可以使用 MySQL 的內(nèi)置加1操作:

UPDATE t_article_counter 
SET read_cnt = read_cnt + 1
WHERE article_id = 1;

這種方式可以使得操作是單行的谓苟,對事物而言是互斥的,因此會將事務(wù)序列化處理避免并發(fā)問題协怒。但是卻會影響并發(fā)請求量涝焙。可以對文章增加多個插槽來提高并發(fā)量孕暇。

CREATE TABLE t_article_counter (
  id INT NOT NULL PRIMARY KEY,
  slot TINYINT UNSIGNED,
  article_id INT,
  read_cnt INT UNSIGNED NOT NULL,
  praise_cnt INT UNSIGNED NOT NULL,
  INDEX(article_id)
);

這時可以創(chuàng)建100個插槽初始化數(shù)據(jù)仑撞,在更新的時候可以這樣操作:

UPDATE t_article_counter
SET read_cnt = read_cnt + 1 
WHERE slot = RAND() * 100 AND article_id = 1;

獲取某篇文章的總閱讀數(shù)時,需要使用一個 SUM 操作:

SELECT SUM(read_cnt) FROM t_article_counter
WHERE article_id = 1;

這種方式實際上是空間換時間妖滔,提高了并發(fā)量隧哮。

總結(jié)

本篇介紹了如何設(shè)計統(tǒng)計數(shù)據(jù)表,關(guān)鍵的核心在于業(yè)務(wù)類型座舍。對于更新頻率低近迁、數(shù)據(jù)量小的表使用實時同步或者直接 SUM 求和問題都不大。而對于大數(shù)據(jù)表簸州,高頻率的更新的情況鉴竭,則可以使用獨立的統(tǒng)計表。同時岸浑,若存在高并發(fā)的情況搏存,統(tǒng)計表中可以考慮每項主體增加多個插槽的方式提高并發(fā)量。如果是周期性地同步數(shù)據(jù)矢洲,也可以使用 Flexviews 物化視圖插件實現(xiàn)璧眠。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市读虏,隨后出現(xiàn)的幾起案子责静,更是在濱河造成了極大的恐慌,老刑警劉巖盖桥,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件灾螃,死亡現(xiàn)場離奇詭異,居然都是意外死亡揩徊,警方通過查閱死者的電腦和手機腰鬼,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門嵌赠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人熄赡,你說我怎么就攤上這事姜挺。” “怎么了彼硫?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵炊豪,是天一觀的道長。 經(jīng)常有香客問我拧篮,道長溜在,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任他托,我火速辦了婚禮,結(jié)果婚禮上仆葡,老公的妹妹穿的比我還像新娘赏参。我一直安慰自己,他們只是感情好沿盅,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布把篓。 她就那樣靜靜地躺著,像睡著了一般腰涧。 火紅的嫁衣襯著肌膚如雪韧掩。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天窖铡,我揣著相機與錄音疗锐,去河邊找鬼。 笑死费彼,一個胖子當著我的面吹牛滑臊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播箍铲,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼雇卷,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了颠猴?” 一聲冷哼從身側(cè)響起关划,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翘瓮,沒想到半個月后贮折,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡资盅,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年脱货,在試婚紗的時候發(fā)現(xiàn)自己被綠了岛都。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡振峻,死狀恐怖臼疫,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扣孟,我是刑警寧澤烫堤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站凤价,受9級特大地震影響鸽斟,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜利诺,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一富蓄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧慢逾,春花似錦立倍、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至君珠,卻和暖如春寝志,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背策添。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工材部, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人唯竹。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓败富,卻偏偏與公主長得像,于是被迫代替她去往敵國和親摩窃。 傳聞我的和親對象是個殘疾皇子兽叮,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容