{eval=Array;=+count(Array);}
我的天啦,一個表九千萬也是了不得了!
我上家公司明確規(guī)定,一張表不能超過5000萬,因為查詢效率會有更大的降低!
無論如何,看下如何優(yōu)化數(shù)據(jù)查詢吧!
①,單庫單表:
1,加索引,一個好的索引能用空間換取查詢時間的大為降低!
2,使用存儲過程:減少sql編譯的時間!
3,優(yōu)化sql:包括聯(lián)合查詢的指向,where,order語句使用索引字段,減少使用多表聯(lián)合查詢,不要使用select *等等!
4,參數(shù)配置:擴大內(nèi)存,調(diào)節(jié)線程池參數(shù)等等!
5,開啟緩存:開啟二級緩存,三級緩存,提升查詢效率!
②,單庫多表:
使用水平拆分(比如按月份),將表分為12張表,然后在代碼端按照月份訪問相應(yīng)月份的表!
使用垂直拆分:很多字段只是作為保存記錄用,(像一些約定,備注啥的字段往往很大),可以將查詢中常常用到的字段放在常用的一張表中做查詢,另一些字段放另一張表中存儲,通過某個唯一索引字段聯(lián)系起來,可以保證查詢效率大為提升(因為磁盤IO減少)!
③,多庫多表:
①,主從讀寫分離:表中數(shù)據(jù)雖然還是一致,但是由于多個從庫讀,主庫寫數(shù)據(jù),大大減少共享鎖的性能開銷!
②,分庫分表:指定一個字段作為,分庫字段,利用hash值或者其它策略,分布在不同的庫里面,在按照相應(yīng)分布策略(比如上面的水平拆分或者垂直拆分),分散到不同的表里!
比如我們現(xiàn)在的數(shù)據(jù)庫設(shè)計為8庫1024表,你的將近一億的數(shù)據(jù)在我們的單張表里面只有不到10W!
雖然理論上,一張表的大小不做任何限制,但是基于查詢效率,索引性能等,不宜超出5000萬數(shù)據(jù)!
關(guān)于多線程,分布式,微服務(wù),數(shù)據(jù)庫,緩存的更多干貨,會繼續(xù)分享,敬請關(guān)注。。
實踐出真知。根據(jù)成本順序依次是:
第一:加索引優(yōu)化sql。盡量避免全盤掃描,另單表索引也不是越多越好。
第二:加緩存。使用redis,memcached,但注意緩存同步更新、設(shè)置失效等問題。
第三:主從復(fù)制,讀寫分離。適合讀多寫少的場景,同步會有延遲。
第四:垂直拆分。可以選用適當(dāng)?shù)闹虚g件Mycat等
第五:水平切分。選擇合理的sharding key,改動表結(jié)構(gòu),將大數(shù)據(jù)字段拆分出去,對經(jīng)常查詢的字段做一定的冗余,同時做好數(shù)據(jù)同步。
當(dāng)然還有優(yōu)化數(shù)據(jù)庫連接配置,根據(jù)業(yè)務(wù)選用不同的數(shù)據(jù)庫引擎等等。
我是一名架構(gòu)師,歡迎關(guān)注,給技術(shù)加點料
我不清楚答題的大部分人是否有真正實踐過,特別是用mysql實踐過。大部分說是加索引、調(diào)整參數(shù)不是說不正確,有效果,但是不能很好的解決問題。說說個人想法:
部分答主的方案的確不敢茍同,糾正如下:
1、select count(*) 和 select count(主鍵) 在現(xiàn)階段的mysql 沒有太大區(qū)別,新版mysql這個對性能影響可以忽略。
2、強烈反對使用存儲過程,后面介紹了使用分表分庫的方案,就更不要用存儲過程了。
3、單表行數(shù)和表數(shù)量,需要找到平衡點。表太多,性能也會下降。
我的回答:
1、單表9000w數(shù)據(jù),mysql存儲不了,想辦法分表分庫。500w數(shù)據(jù)的時候,你就該有這個想法了。只加索引解決不了問題,9000w的單表數(shù)據(jù),很難平衡查找和插入性能,索引稍微多了插入性能也很低。
2、不要再說select count了,放棄匯總查詢的想法,根本查不了。
3、數(shù)據(jù)最終以mysql作為主要存儲,考慮最終查詢的數(shù)據(jù)源放在非關(guān)系的數(shù)據(jù)存儲上,mongo,es都可以考慮下。
4、業(yè)務(wù)場景都是需要實時查詢9000w數(shù)據(jù)嗎?非實時數(shù)據(jù),可以考慮hadoop系大數(shù)據(jù)方案。
5、最后說下,mysql 和oracle,sql server不一樣,不一樣。
是一張表九千萬了嗎?
建議:
第一、表讀居多還是寫?讀的話數(shù)據(jù)庫引擎用myisam ,寫的話InnoDB 而不是MyISAM,因為MyISAM有太多鎖。
第二、升級到MySQL 5.5 ,確保使用buffering功能。
第三,索引確保使用正確,且都在內(nèi)存中,移除沒有必要的索引。
第四、寫場景多嗎? 設(shè)置innodb_buffer_pool_size足夠大來確保更快的寫操作。
第五、按業(yè)務(wù)id取模,分表。
最后,花錢加機器內(nèi)存和用ssd磁盤吧。
作為一個多年的WEB后端程序員,經(jīng)常與各種數(shù)據(jù)庫打交道,下面分享一些自己的處理方式給你。
對于數(shù)據(jù)量這么大的數(shù)據(jù),MySQL提供了以下優(yōu)化方案:
1.常規(guī)方式索引,這里需要注意的是,索引也是一種文件,如果你的服務(wù)器或者數(shù)據(jù)庫內(nèi)存非常小,一次無法將所有的索引文件載入,這個時候索引文件因為要反復(fù)在磁盤和內(nèi)存之間進(jìn)行切換,這樣效果肯定非常不明顯,導(dǎo)致查詢也變慢,所以這種情況可以適當(dāng)增加內(nèi)存,以滿足索引文件一次載入到內(nèi)存進(jìn)行檢索查詢。
2.表分區(qū)保存,對于這么大的數(shù)據(jù),可以根據(jù)具體的需求進(jìn)行表分區(qū)保存,在進(jìn)行表分區(qū)保存的時候,需要注意,一定要根據(jù)具體的需求進(jìn)行分區(qū),這和建立索引是一樣的道理。
3.用程序?qū)崿F(xiàn)分表保存,比如在保存和查詢數(shù)據(jù)的時候,生成主鍵時,可以用某種規(guī)則將其保存在90個表左右,這樣就變成了90個100萬數(shù)據(jù)的表,查詢肯定會提升,不過對于分表保存,目前MySQL數(shù)據(jù)庫對于INNODB存儲引擎沒有提供太多的支持,所以這一切必須由我們自己寫程序來實現(xiàn)。
如果你還有什么問題,可以在評論中留言。
讀寫分離,分庫分表,熱數(shù)據(jù)放內(nèi)存。
讀寫分離:減少寫庫所帶來的行鎖甚至表鎖對查詢的影響,提升查詢效率,同時還可以保證高可用。
在設(shè)計系統(tǒng)之初就設(shè)計好垂直分庫和垂直分表,比如垂直分表:在一張大表中,一些熱數(shù)據(jù)的字段放在一起,一些不常用的而且占用空間比較大的字段放在另外一張表,這樣子做的好處是提升了查詢速度,因為mysql是以頁存儲數(shù)據(jù)的,一頁之中存放的數(shù)據(jù)越多,查詢效率會更高。
另外再配合redis mongodb這些緩存數(shù)據(jù)庫,熱數(shù)據(jù)放進(jìn)去,查詢效率會進(jìn)一步得到提升。
如果上面的方案還無法解決查詢緩慢的問題,可能是因為我們的數(shù)據(jù)量非常大,而且持續(xù)快速增長。我們還可以進(jìn)行水平分庫分表,例如把一張1億數(shù)據(jù)量的大表,水平拆分成10張相同的大表,再水平拆分到10個不同的數(shù)據(jù)庫中。。。
覺得可以的點個贊
9千萬的數(shù)據(jù),如果現(xiàn)在基本不再增長,可以優(yōu)化一下,首先找到性能問題的原因,是sql的問題,還是設(shè)計的問題。為了提高查詢效率,在設(shè)計上可以采用非常規(guī)設(shè)計,比如反范式設(shè)計等。或者把join的表拆開。方法很多,只能根據(jù)具體業(yè)務(wù)來說,你可以把現(xiàn)在的查詢語句列出來,具體分析。9千萬數(shù)據(jù),如果根據(jù)主鍵id查詢,那也能在100ms內(nèi)查詢出來結(jié)果。
如果現(xiàn)在每天還有不少增量數(shù)據(jù),分表就不可避免了。就是把一個表的數(shù)據(jù)分成多個表,這個還是得 根據(jù)業(yè)務(wù)類型來確定,按照時間來分表?還是按照id來分?這個得具體分析。分庫分表帶來的 改動相對較大。
最簡單的方法就是優(yōu)化查詢,第一點,可以建立索引,因為索引可以很大程度優(yōu)化查詢。第二點,可以配置緩存還可以用slow_query_log進(jìn)行分析,這樣很大提升查詢的。第三點,建立分庫分表,因為分庫分表是查詢的殺手锏。第四點,優(yōu)化sql語句,比如子查詢的優(yōu)化等。第五點,就是在連表查詢是要使用Join表的時候使用相當(dāng)類型的例,并將其為索引。
9000萬的話,如果前端訪問量不是過大,單機就可以優(yōu)化
首先應(yīng)該看你們是什么業(yè)務(wù),針對業(yè)務(wù)類型的不同可以采取不同的優(yōu)化方式。
1.如果是線上環(huán)境,對外提供服務(wù),這個表確實是很大了,無論索引設(shè)計的多么合理,進(jìn)行查詢和插入的時候都會耗時較長,性能低下。特別是遇到連表查詢的時候,會更慢。這個時候可以考慮進(jìn)行分表或者分區(qū)表。
1.1分表:是將一個大表按照一定的規(guī)則分解成多張具有獨立存儲空間的實體表,我們可以稱為子表。app讀寫的時候需要先根據(jù)事先定義好的規(guī)則得到對應(yīng)的子表名。
1.2分區(qū)表:和分表相似,都是按照規(guī)則分解表。不同在于分表將大表分解為若干個獨立的實體表,而分區(qū)是將數(shù)據(jù)分段劃分在多個位置存放,可以是同一塊磁盤也可以在不同的機器。分區(qū)后,表面上還是一張表,但數(shù)據(jù)散列到多個位置了。app讀寫的時候操作的還是大表名字,這種方式對程序來說是透明的,無需更改程序。不過要注意sql查詢的時候需要加上可以定位到某個分區(qū)表的條件,否則會是整個大表掃描,性能比未分區(qū)前更慢。
分區(qū)的類型有:
RANGE分區(qū):基于屬于一個給定連續(xù)區(qū)間的列值,把多行分配給分區(qū)。
LIST分區(qū):類似于按RANGE分區(qū),區(qū)別在于LIST分區(qū)是基于列值匹配一個離散值集合中的某個值來進(jìn)行選擇。
HASH分區(qū):基于用戶定義的表達(dá)式的返回值來進(jìn)行選擇的分區(qū),該表達(dá)式使用將要插入到表中的這些行的列值進(jìn)行計算。這個函數(shù)可以包含MySQL 中有效的、產(chǎn)生非負(fù)整數(shù)值的任何表達(dá)式。
KEY分區(qū):類似于按HASH分區(qū),區(qū)別在于KEY分區(qū)只支持計算一列或多列,且MySQL服務(wù)器提供其自身的哈希函數(shù)。必須有一列或多列包含整數(shù)值。
除了分表和分區(qū)表外,還可以采取緩存,redis或者mamecache,降低mysql數(shù)據(jù)庫的壓力。
2.如果是統(tǒng)計業(yè)務(wù),則可以采取別的數(shù)據(jù)庫存儲數(shù)據(jù),像是列數(shù)據(jù)庫,mariadb columnstore ,計算能力比myslq強大很多。
0
回答0
回答0
回答0
回答0
回答0
回答0
回答0
回答0
回答0
回答