日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
「數(shù)據(jù)庫分表優(yōu)化」:提高性能與可擴(kuò)展性(數(shù)據(jù)庫分表優(yōu)化)

數(shù)據(jù)庫分表優(yōu)化:提高性能與可擴(kuò)展性

隨著互聯(lián)網(wǎng)和移動(dòng)互聯(lián)網(wǎng)的迅速發(fā)展,數(shù)據(jù)量增長的速度也越來越快。對(duì)于大型互聯(lián)網(wǎng)企業(yè)來說,數(shù)據(jù)庫性能和可擴(kuò)展性是業(yè)務(wù)發(fā)展的關(guān)鍵。然而,在數(shù)據(jù)量龐大的情況下,單表的數(shù)據(jù)存儲(chǔ)已經(jīng)無法滿足業(yè)務(wù)需求,數(shù)據(jù)庫分表優(yōu)化成為了必不可少的一種手段,本文將對(duì)數(shù)據(jù)庫分表的優(yōu)化方案進(jìn)行探討。

一、什么是數(shù)據(jù)庫分表

數(shù)據(jù)庫分表,就是將一個(gè)表按照某個(gè)規(guī)則,將原本存儲(chǔ)在單張表中的數(shù)據(jù)分成若干個(gè)表進(jìn)行存儲(chǔ),從而達(dá)到提高數(shù)據(jù)庫性能和可擴(kuò)展性的目的。通俗而言,就是在數(shù)據(jù)庫中創(chuàng)建多個(gè)表,以存儲(chǔ)原先一個(gè)表中的所有數(shù)據(jù)。

舉個(gè)例子,假設(shè)我們有一張“用戶信息表”,包含了所有系統(tǒng)用戶的信息,其中每條記錄包括用戶名、密碼、郵箱等信息。隨著用戶數(shù)量的增加,表中的數(shù)據(jù)量也在不斷增長,導(dǎo)致查詢、更新、刪除等操作變得越來越慢,甚至出現(xiàn)服務(wù)器癱瘓的情況。這時(shí),我們可以通過分表來對(duì)“用戶信息表”進(jìn)行優(yōu)化。

二、數(shù)據(jù)庫分表優(yōu)化的實(shí)現(xiàn)方法

實(shí)現(xiàn)數(shù)據(jù)庫分表有多種方法,根據(jù)業(yè)務(wù)特點(diǎn),選擇不同的分表方式。

1.按時(shí)間分表

如果數(shù)據(jù)量主要集中在某一段時(shí)間內(nèi),比如日志信息,可以按照時(shí)間將數(shù)據(jù)分為多個(gè)表,以便更快地查詢分析數(shù)據(jù)。這種分表方式的優(yōu)點(diǎn)是數(shù)據(jù)查詢和統(tǒng)計(jì)非??焖?,缺點(diǎn)是不容易實(shí)現(xiàn)跨區(qū)間查詢。

2.按數(shù)據(jù)類型分表

如果數(shù)據(jù)是按照某個(gè)類型分類的,可以根據(jù)分類進(jìn)行分表,比如商品按照所屬分類進(jìn)行分表。這種分表方式的優(yōu)點(diǎn)是查詢和統(tǒng)計(jì)非??焖?,缺點(diǎn)是增加了表的數(shù)量,增加了維護(hù)的難度。

3.按ID范圍分表

ID范圍分表是指按照主鍵ID的范圍進(jìn)行分表,比如將用戶ID為1-100000的記錄存儲(chǔ)在一張表中,將ID為100001-202300的記錄存儲(chǔ)在另一張表中,以此類推。這種分表方式的優(yōu)點(diǎn)是易于擴(kuò)展、管理,缺點(diǎn)是可能導(dǎo)致查詢性能下降。

4.按hash值分表

按照hash值分表是指根據(jù)數(shù)據(jù)的hash值進(jìn)行分表,比如將hash值為1-1000的記錄存儲(chǔ)在一張表中,將hash值為1001-2023的記錄存儲(chǔ)在另一張表中,以此類推。這種分表方式的優(yōu)點(diǎn)是易于擴(kuò)展、管理,查詢性能均衡;缺點(diǎn)是難以完成跨區(qū)間查詢。

三、數(shù)據(jù)庫分表帶來的好處

1.提高查詢速度

當(dāng)單表數(shù)據(jù)量過大時(shí),一次查詢的時(shí)間會(huì)變得越來越長,通過分表可以降低單表數(shù)據(jù)量,從而提高查詢速度。

2.提高系統(tǒng)性能

當(dāng)單表數(shù)據(jù)量過大時(shí),系統(tǒng)會(huì)出現(xiàn)性能瓶頸,甚至崩潰現(xiàn)象。通過分表,可以使數(shù)據(jù)負(fù)載更加均衡,降低單個(gè)表的請(qǐng)求量,提高系統(tǒng)的性能。

3.易于擴(kuò)展

通過分表,可以很容易地添加新的數(shù)據(jù)節(jié)點(diǎn),支持系統(tǒng)的線性擴(kuò)展,為企業(yè)業(yè)務(wù)發(fā)展提供了更多的空間。

四、注意事項(xiàng)

1. 多個(gè)表之間數(shù)據(jù)的一致性

在進(jìn)行分表優(yōu)化之前,應(yīng)該考慮好多個(gè)表之間數(shù)據(jù)的一致性,確保數(shù)據(jù)的正確性和完整性。

2. 對(duì)索引的合理利用

分表后,數(shù)據(jù)量變小,可以更精細(xì)地設(shè)計(jì)表的索引,提高查詢性能。

3. 保持分表規(guī)則的一致性

分表規(guī)則一定要保持一致性,不可隨意更改。否則可能導(dǎo)致查詢結(jié)果不準(zhǔn)確,甚至系統(tǒng)崩潰等問題。

4. 跨表查詢的設(shè)計(jì)問題

當(dāng)需要跨表查詢時(shí),設(shè)計(jì)查詢方式不能簡單地將多張表的結(jié)果合并,而應(yīng)該通過一些復(fù)雜的算法進(jìn)行查詢。

五、

數(shù)據(jù)庫分表優(yōu)化是一種重要的手段,可以提高數(shù)據(jù)庫的性能和可擴(kuò)展性。但是,在進(jìn)行分表優(yōu)化時(shí),應(yīng)該考慮好多個(gè)表之間的一致性和查詢性能等問題,以保證系統(tǒng)穩(wěn)定和數(shù)據(jù)正確性。同時(shí),不同的分表方案對(duì)應(yīng)著不同的業(yè)務(wù)需求,應(yīng)該根據(jù)實(shí)際情況選擇合適的分表方式。

相關(guān)問題拓展閱讀:

  • 問個(gè)mysql優(yōu)化問題

問個(gè)mysql優(yōu)化問題

在鍵租謹(jǐn)開始演示之前,我們先介紹下兩個(gè)概念。

概念一,數(shù)據(jù)的可選擇性基數(shù),也就是常說的cardinality值。

查詢優(yōu)化器在生成各種執(zhí)行計(jì)劃之前,得先從統(tǒng)計(jì)信息中取得相關(guān)數(shù)據(jù),這樣才能估算每步操作所涉及到的記錄數(shù),而這個(gè)相關(guān)數(shù)據(jù)就是cardinality。簡單來說,就是每個(gè)值在每個(gè)字段中的唯一值分布狀態(tài)。

比如表t1有100行記錄,其中一列為f1。f1中唯一值的個(gè)數(shù)可以是100個(gè),也可以是1個(gè),當(dāng)然也可以是1到100之間的任何一個(gè)數(shù)字。這里唯一值越的多少,就是這個(gè)列的可選擇基數(shù)。

那看到這里我們就明白了,為什么要在基數(shù)高的字段上建立索引,而基數(shù)低的的字段建立索引反而沒有全表掃描來的快。當(dāng)然這個(gè)只是一方面,至于更深入的探討就不在我這篇探討的范圍了。

概念二,關(guān)于HINT的使用。

這里我來說下HINT是什么,在什么時(shí)候用。

HINT簡單來說就是在某些特定的場(chǎng)景下人工協(xié)助MySQL優(yōu)化器的工作,使她生成更優(yōu)的執(zhí)行計(jì)劃。一般來說,優(yōu)化器的執(zhí)行計(jì)劃都是更優(yōu)化的,不過在某些特定場(chǎng)景下,執(zhí)行計(jì)劃可能不是更優(yōu)化。

比如:表t1經(jīng)過大稿基量的頻繁更新操作,(UPDATE,DELETE,INSERT),cardinality已經(jīng)很不準(zhǔn)確了,這時(shí)候剛好執(zhí)行了一條SQL,那么有可能這條SQL的執(zhí)行計(jì)劃就不是更優(yōu)的。為什么說有可能呢?

來看下具體演示

譬如,以下兩條SQL,

A:

select * from t1 where f1 = 20;

B:

select * from t1 where f1 = 30;

如果f1的值剛好頻繁更新的值為30,并且沒有達(dá)到MySQL自動(dòng)更新cardinality值的臨界值或者說用戶設(shè)置了手動(dòng)更新又或者用戶減少了sample page等等,那么對(duì)這兩條語句來說,可能不準(zhǔn)確的就是B了。

這里順帶說下,MySQL提供了自動(dòng)更新和手動(dòng)更新表cardinality值的方法,因篇幅有限,需要的可以查閱手冊(cè)。

那回到正題上,MySQL 8.0 帶來了幾個(gè)HINT,我今天就舉個(gè)index_merge的例子。

示例表結(jié)構(gòu):

mysql> desc t1;+++——+—–++–+| Field      | Type| Null | Key | Default | Extra|+++——+—–++–+| id| int(11)      | NO   | PRI | NULL    | auto_increment || rank| int(11)      | YES  | MUL | NULL    |  || rank| int(11)      | YES  | MUL | NULL    |  || log_time   | datetime     | YES  | MUL | NULL    |  || prefix_uid | varchar(100) | YES  |     | NULL    |  || desc| text| YES  |     | NULL    |  || rank| int(11)      | YES  | MUL | NULL    |  型啟|+++——+—–++–+7 rows in set (0.00 sec)

表記錄數(shù):

mysql> select count(*) from t1;++| count(*) |++||++1 row in set (0.01 sec)

這里我們兩條經(jīng)典的SQL:

SQL C:

select * from t1 where rank1 = 1 or rank2 = 2 or rank3 = 2;

SQL D:

select * from t1 where rank1 =100  and rank2 =100  and rank3 =100;

表t1實(shí)際上在rank1,rank2,rank3三列上分別有一個(gè)二級(jí)索引。

那我們來看SQL C的查詢計(jì)劃。

顯然,沒有用到任何索引,掃描的行數(shù)為32023,cost為3243.65。

mysql> explain  format=json select * from t1  where rank1 =1 or rank2 = 2 or rank3 = 2\G*************************** 1. row ***************************EXPLAIN: {  “query_block”: {    “select_id”: 1,    “cost_info”: {      “query_cost”: “3243.65”    },    “table”: {      “table_name”: “t1”,      “access_type”: “ALL”,      “possible_keys”: ,      “rows_examined_per_scan”: 32023,      “rows_produced_per_join”: 115,      “filtered”: “0.36”,      “cost_info”: {“read_cost”: “3232.07”,”eval_cost”: “11.58”,”prefix_cost”: “3243.65”,”data_read_per_join”: “49K”      },      “used_columns”: ,      “attached_condition”: “((`ytt`.`t1`.`rank1` = 1) or (`ytt`.`t1`.`rank2` = 2) or (`ytt`.`t1`.`rank3` = 2))”    }  }}1 row in set, 1 warning (0.00 sec)

我們加上hint給相同的查詢,再次看看查詢計(jì)劃。

這個(gè)時(shí)候用到了index_merge,union了三個(gè)列。掃描的行數(shù)為1103,cost為441.09,明顯比之前的快了好幾倍。

mysql> explain  format=json select /*+ index_merge(t1) */ * from t1  where rank1 =1 or rank2 = 2 or rank3 = 2\G*************************** 1. row ***************************EXPLAIN: {  “query_block”: {    “select_id”: 1,    “cost_info”: {      “query_cost”: “441.09”    },    “table”: {      “table_name”: “t1”,      “access_type”: “index_merge”,      “possible_keys”: ,      “key”: “union(idx_rank1,idx_rank2,idx_rank3)”,      “key_length”: “5,5,5”,      “rows_examined_per_scan”: 1103,      “rows_produced_per_join”: 1103,      “filtered”: “100.00”,      “cost_info”: {“read_cost”: “330.79”,”eval_cost”: “110.30”,”prefix_cost”: “441.09”,”data_read_per_join”: “473K”      },      “used_columns”: ,      “attached_condition”: “((`ytt`.`t1`.`rank1` = 1) or (`ytt`.`t1`.`rank2` = 2) or (`ytt`.`t1`.`rank3` = 2))”    }  }}1 row in set, 1 warning (0.00 sec)

我們?cè)倏聪耂QL D的計(jì)劃:

不加HINT,

mysql> explain format=json select * from t1 where rank1 =100 and rank2 =100 and rank3 =100\G*************************** 1. row ***************************EXPLAIN: {  “query_block”: {    “select_id”: 1,    “cost_info”: {      “query_cost”: “534.34”    },    “table”: {      “table_name”: “t1”,      “access_type”: “ref”,      “possible_keys”: ,      “key”: “idx_rank1”,      “used_key_parts”: ,      “key_length”: “5”,      “ref”: ,      “rows_examined_per_scan”: 555,      “rows_produced_per_join”: 0,      “filtered”: “0.07”,      “cost_info”: {“read_cost”: “478.84”,”eval_cost”: “0.04”,”prefix_cost”: “534.34”,”data_read_per_join”: “176”      },      “used_columns”: ,      “attached_condition”: “((`ytt`.`t1`.`rank3` = 100) and (`ytt`.`t1`.`rank2` = 100))”    }  }}1 row in set, 1 warning (0.00 sec)

加了HINT,

mysql> explain format=json select /*+ index_merge(t1)*/ * from t1 where rank1 =100 and rank2 =100 and rank3 =100\G*************************** 1. row ***************************EXPLAIN: {  “query_block”: {    “select_id”: 1,    “cost_info”: {      “query_cost”: “5.23”    },    “table”: {      “table_name”: “t1”,      “access_type”: “index_merge”,      “possible_keys”: ,      “key”: “intersect(idx_rank1,idx_rank2,idx_rank3)”,      “key_length”: “5,5,5”,      “rows_examined_per_scan”: 1,      “rows_produced_per_join”: 1,      “filtered”: “100.00”,      “cost_info”: {“read_cost”: “5.13”,”eval_cost”: “0.10”,”prefix_cost”: “5.23”,”data_read_per_join”: “440”      },      “used_columns”: ,      “attached_condition”: “((`ytt`.`t1`.`rank3` = 100) and (`ytt`.`t1`.`rank2` = 100) and (`ytt`.`t1`.`rank1` = 100))”    }  }}1 row in set, 1 warning (0.00 sec)

對(duì)比下以上兩個(gè),加了HINT的比不加HINT的cost小了100倍。

總結(jié)下,就是說表的cardinality值影響這張的查詢計(jì)劃,如果這個(gè)值沒有正常更新的話,就需要手工加HINT了。相信MySQL未來的版本會(huì)帶來更多的HINT。

在一張有幾百萬個(gè)大數(shù)據(jù)的表中,MySQL的處理引擎會(huì)查找得很慢,這時(shí),就必須采用分表甚至分庫的方法。

你可以參考這篇文章:《MySQL大數(shù)據(jù)處理》

摘錄如下:

一、概述

分表是個(gè)目前算是比較炒的比較流行的概念,特別是在大負(fù)載的情況下,分表是一個(gè)良好分散數(shù)據(jù)庫壓力的好方法。

首先要了解為什么要分表,分表的好處是什么。我們先來大概了解以下一個(gè)數(shù)據(jù)庫執(zhí)行SQL的過程:

接收到SQL –> 放入SQL執(zhí)行隊(duì)列 –> 使用分析器分解SQL –> 按照分析結(jié)果進(jìn)行數(shù)據(jù)的提取或者修改 –> 返回處理結(jié)果

當(dāng)然,這個(gè)流程圖不一定正確,殲明唯這只是我自己主觀意識(shí)上這么我認(rèn)為。那么這個(gè)處理過程當(dāng)中,最容易出現(xiàn)問題的是什么?就是說,如果前一個(gè)SQL沒

有執(zhí)行完畢的話,后面的SQL是不會(huì)執(zhí)行的,因?yàn)闉榱吮WC數(shù)據(jù)的完整性,必須對(duì)數(shù)據(jù)表文件進(jìn)行鎖定,包括共享鎖和獨(dú)享鎖兩種鎖定。共享鎖是在鎖定的期間,

其它線程也可以訪問這個(gè)數(shù)據(jù)文件,但是不允許修改操作,相應(yīng)的,獨(dú)享鎖就是整個(gè)文件就是歸一個(gè)線程所有,其它線程無法訪問這個(gè)數(shù)據(jù)文件。一般MySQL中

最快的存儲(chǔ)引擎MyISAM,它是基于表鎖定的,就是說如果一鎖定的話,那么整個(gè)數(shù)據(jù)文件外部都無法訪問,必須等前一個(gè)操作完成后,才能接收下一個(gè)操作,

那么在這個(gè)前一個(gè)操作沒有執(zhí)行完成,后一個(gè)操作等待在隊(duì)列里無法執(zhí)行的情況叫做阻塞,一般我們通俗意義上叫做“鎖表”。

鎖表直接導(dǎo)致的后果是什么?就是大量的SQL無法立即執(zhí)行,必須等隊(duì)列前面的SQL全部執(zhí)行完畢才能繼續(xù)執(zhí)行。這個(gè)無法執(zhí)行的SQL就會(huì)導(dǎo)致沒有結(jié)果,或者延遲嚴(yán)重,影響用戶體驗(yàn)。

特別是對(duì)于一些使用比較頻繁的表,比如SNS系統(tǒng)中的用戶信息表、論壇系統(tǒng)中的帖子表等等,都是訪問量大很大的表,為了保證數(shù)據(jù)的快速提取返回給用戶,必須使用一些處理方式來解決這個(gè)問題,這個(gè)就是我今天要聊到的分表技術(shù)。

分表技術(shù)顧名思義,就是把若干個(gè)存儲(chǔ)相同類型數(shù)據(jù)的表分成幾個(gè)表分表存儲(chǔ),在提取數(shù)據(jù)的時(shí)候,不同的用戶訪問不同的表,互不沖突,減少鎖表的幾

率。比如,目前保存用戶分表有兩個(gè)表,一個(gè)是user_1表,還有一個(gè)是 user_2 表,兩個(gè)表保存了不同的用戶信息,user_1

保存了前10萬的用戶信息,user_2保存了后10萬名用戶的信息,現(xiàn)在如果同時(shí)查詢用戶 heiyeluren1 和 heiyeluren2

這個(gè)兩個(gè)用戶,那么就是分表從不同的表提取出來,減少鎖表的可能。

我下面要講述的兩種分表方法我自己都沒有實(shí)驗(yàn)過,不保證準(zhǔn)確能用,只是提供一個(gè)設(shè)計(jì)思路。下面關(guān)于分表的例子我假設(shè)是在一個(gè)貼吧系統(tǒng)的基礎(chǔ)上來進(jìn)行處理和構(gòu)建的。(如果沒有用過貼吧的用戶趕緊Google一下)

二、基于基礎(chǔ)表的分表處理

這個(gè)基于基槐穗礎(chǔ)表的分表處理方式大致的思想就是:一個(gè)主要表,保存了所有的基本信息,如果某個(gè)項(xiàng)目需要找到它所存儲(chǔ)的表,那么必須從這個(gè)基礎(chǔ)表中

查找出對(duì)應(yīng)的表名等項(xiàng)目,好直接訪問這個(gè)表。如果覺得這個(gè)基礎(chǔ)表速度不夠快,可以完全把整個(gè)基礎(chǔ)表保存在緩存或者內(nèi)存中,方便有效的查詢。

我們基于貼吧的情況,構(gòu)建假設(shè)如下的3張表:

1. 貼吧版塊表: 保存貼吧中版塊的信息

2. 貼吧主題表:保存貼吧中版塊中的主題信息,用于瀏覽

3. 貼吧回復(fù)表:保存主題的原始內(nèi)容和回復(fù)內(nèi)容

“貼吧版塊表”包含如下字段:

版塊IDboard_idint(10)

版塊名稱    board_name      char(50)

子表IDtable_idallint(5)

產(chǎn)生時(shí)間    createddatetime

“貼吧主題表”包含如下字段:

主題IDtopic_idint(10)

主題名稱topic_name     char(255)

版塊IDboard_idint(10)

創(chuàng)建時(shí)間createddatetime

“貼吧回復(fù)表”的字段如下:

回復(fù)IDreply_idint(10)

回復(fù)內(nèi)容      reply_texttext

主題IDtopic_idint(10)

版塊ID氏培 board_idint(10)

創(chuàng)建時(shí)間      createddatetime

那么上面保存了我們整個(gè)貼吧中的表結(jié)構(gòu)信息,三個(gè)表對(duì)應(yīng)的關(guān)系是:

版塊 –> 多個(gè)主題

主題 –> 多個(gè)回復(fù)

那么就是說,表文件大小的關(guān)系是:

版塊表文件 

所以基本可以確定需要對(duì)主題表和回復(fù)表進(jìn)行分表,已增加我們數(shù)據(jù)檢索查詢更改時(shí)候的速度和性能。

看了上面的表結(jié)構(gòu),會(huì)明顯發(fā)現(xiàn),在“版塊表”中保存了一個(gè)”table_id”字段,這個(gè)字段就是用于保存一個(gè)版塊對(duì)應(yīng)的主題和回復(fù)都是分表保存在什么表里的。

比如我們有一個(gè)叫做“PHP”的貼吧,board_id是1,子表ID也是1,那么這條記錄就是:

board_id | board_name | table_id | created

1 | PHP | 1 |:30:12

相應(yīng)的,如果我需要提取“PHP”吧里的所有主題,那么就必須按照表里保存的table_id來組合一個(gè)存儲(chǔ)了主題的表名稱,比如我們主題表的前綴是“topic_”,那么組合出來“PHP”吧對(duì)應(yīng)的主題表應(yīng)該是:“topic_1”,那么我們執(zhí)行:

SELECT * FROM topic_1 WHERE board_id = 1 ORDER BY topic_id DESC LIMIT 10

這樣就能夠獲取這個(gè)主題下面回復(fù)列表,方便我們進(jìn)行查看,如果需要查看某個(gè)主題下面的回復(fù),我們可以繼續(xù)使用版塊表中保存的“table_id”來進(jìn)行查詢。比如我們回復(fù)表的前綴是“reply_”,那么就可以組合出“PHP”吧的ID為1的主題的回復(fù):

SELECT * FROM reply_1 WHERE topic_id = 1 ORDER BY reply_id DESC LIMIT 10

這里,我們能夠清晰的看到,其實(shí)我們這里使用了基礎(chǔ)表,基礎(chǔ)表就是我們的版塊表。那么相應(yīng)的,肯定會(huì)說:基礎(chǔ)表的數(shù)據(jù)量大了以后如何保證它的速度和效率?

當(dāng)然,我們就必須使得這個(gè)基礎(chǔ)表保持更好的速度和性能,比如,可以采用MySQL的內(nèi)存表來存儲(chǔ),或者保存在內(nèi)存當(dāng)中,比如Memcache之類的內(nèi)存緩存等等,可以按照實(shí)際情況來進(jìn)行調(diào)整。

一般基于基礎(chǔ)表的分表機(jī)制在SNS、交友、論壇等Web2.0網(wǎng)站中是個(gè)比較不錯(cuò)的解決方案,在這些網(wǎng)站中,完全可以單獨(dú)使用一個(gè)表來來保存基本標(biāo)識(shí)和目標(biāo)表之間的關(guān)系。使用表保存對(duì)應(yīng)關(guān)系的好處是以后擴(kuò)展非常方便,只需要增加一個(gè)表記錄。

【優(yōu)勢(shì)】增加刪除節(jié)點(diǎn)非常方便,為后期升級(jí)維護(hù)帶來很大便利

【劣勢(shì)】需要增加表或者對(duì)某一個(gè)表進(jìn)行操作,還是無法離開數(shù)據(jù)庫,會(huì)產(chǎn)生瓶頸

三、基于Hash算法的分表處理

我們知道Hash表就是通過某個(gè)特殊的Hash算法計(jì)算出的一個(gè)值,這個(gè)值必須是惟一的,并且能夠使用這個(gè)計(jì)算出來的值查找到需要的值,這個(gè)叫做哈希表。

我們?cè)诜直砝锏膆ash算法跟這個(gè)思想類似:通過一個(gè)原始目標(biāo)的ID或者名稱通過一定的hash算法計(jì)算出數(shù)據(jù)存儲(chǔ)表的表名,然后訪問相應(yīng)的表。

繼續(xù)拿上面的貼吧來說,每個(gè)貼吧有版塊名稱和版塊ID,那么這兩項(xiàng)值是固定的,并且是惟一的,那么我們就可以考慮通過對(duì)這兩項(xiàng)值中的一項(xiàng)進(jìn)行一些運(yùn)算得出一個(gè)目標(biāo)表的名稱。

現(xiàn)在假如我們針對(duì)我們這個(gè)貼吧系統(tǒng),假設(shè)系統(tǒng)更大允許1億條數(shù)據(jù),考慮每個(gè)表保存100萬條記錄,那么整個(gè)系統(tǒng)就不超過100個(gè)表就能夠容納。按照這個(gè)標(biāo)準(zhǔn),我們假設(shè)在貼吧的版塊ID上進(jìn)行hash,獲得一個(gè)key值,這個(gè)值就是我們的表名,然后訪問相應(yīng)的表。

我們構(gòu)造一個(gè)簡單的hash算法:

function get_hash($id){

     $str = bin2hex($id);

     $hash = substr($str, 0, 4);

     if (strlen($hash)

$hash = str_pad($hash, 4, “0”);

     }

     return $hash;

}

算法大致就是傳入一個(gè)版塊ID值,然后函數(shù)返回一個(gè)4位的字符串,如果字符串長度不夠,使用0進(jìn)行補(bǔ)全。

比如:get_hash(1),輸出的結(jié)果是“3100”,輸入:get_hash(23819),得到的結(jié)果是:3233,那么我們經(jīng)過簡單的跟表前綴組合,就能夠訪問這個(gè)表了。那么我們需要訪問ID為1的內(nèi)容時(shí)候哦,組合的表將是:topic_3100、reply_3100,那么就可以直接對(duì)目標(biāo)表進(jìn)行訪問了。

當(dāng)然,使用hash算法后,有部分?jǐn)?shù)據(jù)是可能在同一個(gè)表的,這一點(diǎn)跟hash表不同,hash表是盡量解決沖突,我們這里不需要,當(dāng)然同樣需要預(yù)測(cè)和分析表數(shù)據(jù)可能保存的表名。

如果需要存儲(chǔ)的數(shù)據(jù)更多,同樣的,可以對(duì)版塊的名字進(jìn)行hash操作,比如也是上面的二進(jìn)制轉(zhuǎn)換成十六進(jìn)制,因?yàn)闈h字比數(shù)字和字母要多很多,那么重復(fù)幾率更小,但是可能組合成的表就更多了,相應(yīng)就必須考慮一些其它的問題。

歸根結(jié)底,使用hash方式的話必須選擇一個(gè)好的hash算法,才能生成更多的表,然數(shù)據(jù)查詢的更迅速。

【優(yōu)點(diǎn)hash算法直接得出目標(biāo)表名稱,效率很高】通過

【劣勢(shì)】擴(kuò)展性比較差,選擇了一個(gè)hash算法,定義了多少數(shù)據(jù)量,以后只能在這個(gè)數(shù)據(jù)量上跑,不能超過過這個(gè)數(shù)據(jù)量,可擴(kuò)展性稍差

四、其它問題

1. 搜索問題

現(xiàn)在我們已經(jīng)進(jìn)行分表了,那么就無法直接對(duì)表進(jìn)行搜索,因?yàn)槟銦o法對(duì)可能系統(tǒng)中已經(jīng)存在的幾十或者幾百個(gè)表進(jìn)行檢索,所以搜索必須借助第三方的組件來進(jìn)行,比如Lucene作為站內(nèi)搜索引擎是個(gè)不錯(cuò)的選擇。

2. 表文件問題

我們知道MySQL的MyISAM引擎每個(gè)表都會(huì)生成三個(gè)文件,*.frm、*.MYD、*.MYI

三個(gè)文件,分表用來保存表結(jié)構(gòu)、表數(shù)據(jù)和表索引。Linux下面每個(gè)目錄下的文件數(shù)量更好不要超過1000個(gè),不然檢索數(shù)據(jù)將更慢,那么每個(gè)表都會(huì)生成三

個(gè)文件,相應(yīng)的如果分表超過300個(gè)表,那么將檢索非常慢,所以這時(shí)候就必須再進(jìn)行分,比如在進(jìn)行數(shù)據(jù)庫的分離。

使用基礎(chǔ)表,我們可以新增加一個(gè)字段,用來保存這個(gè)表保存在什么數(shù)據(jù)。使用Hash的方式,我們必須截取hash值中第幾位來作為數(shù)據(jù)庫的名字。這樣,完好的解決這個(gè)問題。

五、總結(jié)

在大負(fù)載應(yīng)用當(dāng)中,數(shù)據(jù)庫一直是個(gè)很重要的瓶頸,必須要突破,本文講解了兩種分表的方式,希望對(duì)很多人能夠有啟發(fā)的作用。當(dāng)然,本文代碼和設(shè)想沒有經(jīng)過任何代碼測(cè)試,所以無法保證設(shè)計(jì)的完全準(zhǔn)確實(shí)用,具體還是需要讀者在使用過程當(dāng)中認(rèn)真分析實(shí)施。

  數(shù)據(jù)庫優(yōu)化的問題需要從多個(gè)角度考慮:

  一、針對(duì)數(shù)據(jù)庫結(jié)構(gòu)和查詢的優(yōu)化:

  在一般的應(yīng)用中,合理的數(shù)據(jù)表結(jié)構(gòu)和索引的設(shè)計(jì),能夠更大化螞棗查詢性能。即時(shí)在千萬級(jí)別的數(shù)據(jù)表中,針對(duì)主鍵的查詢也會(huì)非??焖?。在數(shù)據(jù)量太大的情況下,沒有使用索引的查詢可能會(huì)非常緩慢。where條件會(huì)用到的字段中,要盡量都加上索引。模糊查詢可以通過全文索引來優(yōu)化。另外,單條記錄的長短也會(huì)對(duì)查詢速率產(chǎn)生一定的影響(記錄越長,磁盤讀取數(shù)據(jù)時(shí)需要移動(dòng)的距離就越長)。一些關(guān)鍵的數(shù)據(jù)更好放在小表中。存儲(chǔ)引擎的選擇也很重要。MYISAM引擎的查詢性能更好,而且支持全文索引。MYISAM的索引是壓縮存儲(chǔ)的,可以節(jié)約磁盤空間。更重要的時(shí),它可以將更多的索引加載到內(nèi)存中,大大提畢碰高查詢效率。

  二、針對(duì)架構(gòu)的優(yōu)化:

  在高并發(fā)的應(yīng)用中,僅僅針對(duì)數(shù)據(jù)庫層面的優(yōu)化已經(jīng)力不從心。數(shù)據(jù)庫的能力是有限的,更優(yōu)秀的數(shù)據(jù)庫也存在性能瓶頸。大量的并發(fā)查詢將導(dǎo)致數(shù)據(jù)悶數(shù)拆庫不堪重負(fù)。主從庫、讀寫分離是常見的優(yōu)化方式。對(duì)于一些經(jīng)常訪問的熱數(shù)據(jù),每次都執(zhí)行數(shù)據(jù)庫查詢會(huì)造成資源浪費(fèi),而且非常低效。如果將這些熱的數(shù)據(jù)以key-value(鍵和值)的方式存儲(chǔ)在內(nèi)存中,可以更大化性能。

  一些熱門的應(yīng)用,如你提到的微博,除了做好數(shù)據(jù)庫方面的優(yōu)化外,架構(gòu)優(yōu)化非常關(guān)鍵。本例中,可以為每個(gè)用戶單獨(dú)存儲(chǔ)好友的最新微博。在用戶發(fā)布微博時(shí),將這條微博的ID存儲(chǔ)在所有好友的“最新微博”中。數(shù)據(jù)滿30條時(shí),同時(shí)刪除舊的數(shù)據(jù)。這樣在獲取好友最新微博時(shí),不需要查詢數(shù)據(jù)庫,效率非常高。

數(shù)據(jù)庫分表優(yōu)化的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于數(shù)據(jù)庫分表優(yōu)化,「數(shù)據(jù)庫分表優(yōu)化」:提高性能與可擴(kuò)展性,問個(gè)mysql優(yōu)化問題的信息別忘了在本站進(jìn)行查找喔。

香港服務(wù)器選創(chuàng)新互聯(lián),2H2G首月10元開通。
創(chuàng)新互聯(lián)(www.cdcxhl.com)互聯(lián)網(wǎng)服務(wù)提供商,擁有超過10年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn)。專業(yè)提供云主機(jī)、虛擬主機(jī)、域名注冊(cè)、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。


當(dāng)前文章:「數(shù)據(jù)庫分表優(yōu)化」:提高性能與可擴(kuò)展性(數(shù)據(jù)庫分表優(yōu)化)
當(dāng)前鏈接:http://www.5511xx.com/article/dhhcoid.html