主頁 > 知識(shí)庫 > 詳解MySQL數(shù)據(jù)庫千萬級(jí)數(shù)據(jù)查詢和存儲(chǔ)

詳解MySQL數(shù)據(jù)庫千萬級(jí)數(shù)據(jù)查詢和存儲(chǔ)

熱門標(biāo)簽:Linux服務(wù)器 AI電銷 地方門戶網(wǎng)站 百度競(jìng)價(jià)排名 呼叫中心市場(chǎng)需求 網(wǎng)站排名優(yōu)化 鐵路電話系統(tǒng) 服務(wù)外包

百萬級(jí)數(shù)據(jù)處理方案

數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)設(shè)計(jì)

表字段設(shè)計(jì)

  • 表字段 not null,因?yàn)?null 值很難查詢優(yōu)化且占用額外的索引空間,推薦默認(rèn)數(shù)字 0。
  • 數(shù)據(jù)狀態(tài)類型的字段,比如 status, type 等等,盡量不要定義負(fù)數(shù),如 -1。因?yàn)檫@樣可以加上 UNSIGNED,數(shù)值容量就會(huì)擴(kuò)大一倍。
  • 可以的話用 TINYINT、SMALLINT 等代替 INT,盡量不使用 BIGINT,因?yàn)檎嫉目臻g更小。
  • 字符串類型的字段會(huì)比數(shù)字類型占的空間更大,所以盡量用整型代替字符串,很多場(chǎng)景是可以通過編碼邏輯來實(shí)現(xiàn)用整型代替的。
  • 字符串類型長(zhǎng)度不要隨意設(shè)置,保證滿足業(yè)務(wù)的前提下盡量小。
  • 用整型來存 IP。
  • 單表不要有太多字段,建議在20以內(nèi)。
  • 為能預(yù)見的字段提前預(yù)留,因?yàn)閿?shù)據(jù)量越大,修改數(shù)據(jù)結(jié)構(gòu)越耗時(shí)。

索引設(shè)計(jì)

  • 索引,空間換時(shí)間的優(yōu)化策略,基本上根據(jù)業(yè)務(wù)需求設(shè)計(jì)好索引,足以應(yīng)付百萬級(jí)的數(shù)據(jù)量,養(yǎng)成使用 explain 的習(xí)慣,關(guān)于 explain 也可以訪問:explain 讓你的 sql 寫的更踏實(shí)了解更多。
  • 一個(gè)常識(shí):索引并不是越多越好,索引是會(huì)降低數(shù)據(jù)寫入性能的。
  • 索引字段長(zhǎng)度盡量短,這樣能夠節(jié)省大量索引空間;
  • 取消外鍵,可交由程序來約束,性能更好。
  • 復(fù)合索引的匹配最左列規(guī)則,索引的順序和查詢條件保持一致,盡量去除沒必要的單列索引。
  • 值分布較少的字段(不重復(fù)的較少)不適合建索引,比如像性別這種只有兩三個(gè)值的情況字段建立索引意義不大。
  • 需要排序的字段建議加上索引,因?yàn)樗饕菚?huì)排序的,能提高查詢性能。
  • 字符串字段使用前綴索引,不使用全字段索引,可大幅減小索引空間。

查詢語句優(yōu)化

  • 盡量使用短查詢替代復(fù)雜的內(nèi)聯(lián)查詢。
  • 查詢不使用 select *,盡量查詢帶索引的字段,避免回表。
  • 盡量使用 limit 對(duì)查詢數(shù)量進(jìn)行限制。
  • 查詢字段盡量落在索引上,尤其是復(fù)合索引,更需要注意最左前綴匹配。
  • 拆分大的 delete / insert 操作,一方面會(huì)鎖表,影響其他業(yè)務(wù)操作,還有一方面是 MySQL 對(duì) sql 長(zhǎng)度也是有限制的。
  • 不建議使用 MySQL 的函數(shù),計(jì)算等,可先由程序處理,從上面提的一些點(diǎn)會(huì)發(fā)現(xiàn),能交由程序處理的盡量不要把壓力轉(zhuǎn)至數(shù)據(jù)庫上。因?yàn)槎鄶?shù)的服務(wù)器性能瓶頸都在數(shù)據(jù)庫上。
  • 查詢 count,性能:count(1) = count(*) > count(主鍵) > count(其他字段)。
  • 查詢操作符能用 between 則不用 in,能用 in 則不用 or。
  • 避免使用!=或<>、IS NULL或IS NOT NULL、IN ,NOT IN等這樣的操作符,因?yàn)檫@些查詢無法使用索引。
  • sql 盡量簡(jiǎn)單,少用 join,不建議兩個(gè) join 以上。

千萬級(jí)數(shù)據(jù)處理方案

數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)設(shè)計(jì)

到了這個(gè)階段的數(shù)據(jù)量,數(shù)據(jù)本身已經(jīng)有很大的價(jià)值了,數(shù)據(jù)除了滿足常規(guī)業(yè)務(wù)需求外,還會(huì)有一些數(shù)據(jù)分析的需求。而這個(gè)時(shí)候數(shù)據(jù)可變動(dòng)性不高,基本上不會(huì)考慮修改原有結(jié)構(gòu),一般會(huì)考慮從分區(qū),分表,分庫三方面做優(yōu)化:

分區(qū):

  • 分區(qū)是根據(jù)一定的規(guī)則,數(shù)據(jù)庫把一個(gè)表分解成多個(gè)更小的、更容易管理的部分,是一種水平劃分。對(duì)應(yīng)用來說是完全透明的,不影響應(yīng)用的業(yè)務(wù)邏輯,即不用修改代碼。因此能存更多的數(shù)據(jù),查詢,刪除也支持按分區(qū)來操作,從而達(dá)到優(yōu)化的目的。如果有考慮分區(qū),可以提前做準(zhǔn)備,避免下列一些限制:
  • 一個(gè)表最多只能有1024個(gè)分區(qū)(mysql5.6之后支持8192個(gè)分區(qū))。但你實(shí)際操作的時(shí)候,最好不要一次性打開超過 100 個(gè)分區(qū),因?yàn)榇蜷_分區(qū)也是有時(shí)間損耗的。
  • 如果分區(qū)字段中有主鍵或者唯一索引列,那么所有主鍵列和唯一索引列都必須包含進(jìn)來,如果表中有主鍵或唯一索引,那么分區(qū)鍵必須是主鍵或唯一索引。
  • 分區(qū)表中無法使用外鍵約束。
  • NULL值會(huì)使分區(qū)過濾無效,這樣會(huì)被放入默認(rèn)的分區(qū)里,請(qǐng)千萬不要讓分區(qū)字段出現(xiàn) NULL。
  • 所有分區(qū)必須使用相同的存儲(chǔ)引擎。

分表:

分表分水平分表和垂直分表。

水平分表即拆分成數(shù)據(jù)結(jié)構(gòu)相同的各個(gè)小表,如拆分成 table1, table2...,從而緩解數(shù)據(jù)庫讀寫壓力。

垂直分表即將一些字段分出去形成一個(gè)新表,各個(gè)表數(shù)據(jù)結(jié)構(gòu)不相同,可以優(yōu)化高并發(fā)下鎖表的情況。

可想而知,分表的話,程序的邏輯是需要做修改的,所以,一般是在項(xiàng)目初期時(shí),預(yù)見到大數(shù)據(jù)量的情況,才會(huì)考慮分表。后期階段不建議分表,成本很大。

分庫:

分庫一般是主從模式,一個(gè)數(shù)據(jù)庫服務(wù)器主節(jié)點(diǎn)復(fù)制到一個(gè)或多個(gè)從節(jié)點(diǎn)多個(gè)數(shù)據(jù)庫,主庫負(fù)責(zé)寫操作,從庫負(fù)責(zé)讀操作,從而達(dá)到主從分離,高可用,數(shù)據(jù)備份等優(yōu)化目的。

當(dāng)然,主從模式也會(huì)有一些缺陷,主從同步延遲,binlog 文件太大導(dǎo)致的問題等等,這里不細(xì)講(筆者也學(xué)不動(dòng)了)。

其他:

冷熱表隔離。對(duì)于歷史的數(shù)據(jù),查詢和使用的人數(shù)少的情況,可以移入另一個(gè)冷數(shù)據(jù)庫里,只提供查詢用,來緩解熱表數(shù)據(jù)量大的情況。

數(shù)據(jù)庫表主鍵設(shè)計(jì)

數(shù)據(jù)庫主鍵設(shè)計(jì),個(gè)人推薦帶有時(shí)間屬性的自增長(zhǎng)數(shù)字ID。(分布式自增長(zhǎng)ID生成算法)

  • 雪花算法
  • 百度分布式ID算法
  • 美團(tuán)分布式ID算法

為什么要使用這些算法呢,這個(gè)與MySQL數(shù)據(jù)存儲(chǔ)結(jié)構(gòu)有關(guān)

從業(yè)務(wù)上來說:

在設(shè)計(jì)數(shù)據(jù)庫時(shí)不需要費(fèi)盡心思去考慮設(shè)置哪個(gè)字段為主鍵。然后是這些字段只是理論上是唯一的,例如使用圖書編號(hào)為主鍵,這個(gè)圖書編號(hào)只是理論上來說是唯一的,但實(shí)踐中可能會(huì)出現(xiàn)重復(fù)的情況。所以還是設(shè)置一個(gè)與業(yè)務(wù)無關(guān)的自增ID作為主鍵,然后增加一個(gè)圖書編號(hào)的唯一性約束。

從技術(shù)上來說:

1.如果表使用自增主鍵,那么每次插入新的記錄,記錄就會(huì)順序添加到當(dāng)前索引節(jié)點(diǎn)的后續(xù)位置,當(dāng)一頁寫滿,就會(huì)自動(dòng)開辟一個(gè)新的頁。 總的來說就是可以提高查詢和插入的性能。

2.對(duì)InnoDB來說主鍵索引既存儲(chǔ)索引值,又在葉子節(jié)點(diǎn)中存儲(chǔ)行的數(shù)據(jù),也就是說數(shù)據(jù)文件本身就是按照b+樹方式存放數(shù)據(jù)的。

3.如果沒有定義主鍵,則會(huì)使用非空的UNIQUE鍵做主鍵 ; 如果沒有非空的UNIQUE鍵,則系統(tǒng)生成一個(gè)6字節(jié)的rowid做主鍵;聚簇索引中,N行形成一個(gè)頁(一頁通常大小為16K)。如果碰到不規(guī)則數(shù)據(jù)插入時(shí),為了保持B+樹的平衡,會(huì)造成頻繁的頁分裂和頁旋轉(zhuǎn),插入速度比較慢。所以聚簇索引的主鍵值應(yīng)盡量是連續(xù)增長(zhǎng)的值,而不是隨機(jī)值(不要用隨機(jī)字符串或UUID)。

4.故對(duì)于InnoDB的主鍵,盡量用整型,而且是遞增的整型。這樣在存儲(chǔ)/查詢上都是非常高效的。

MySQL面試題

MySQL數(shù)據(jù)庫千萬級(jí)數(shù)據(jù)查詢優(yōu)化方案

limit分頁查詢?cè)娇亢蟛樵冊(cè)铰?。這也讓我們得出一個(gè)結(jié)論:

1、limit語句的查詢時(shí)間與起始記錄的位置成正比。

2、mysql的limit語句是很方便,但是對(duì)記錄很多的表并不適合直接使用

表使用InnoDB作為存儲(chǔ)引擎,id作為自增主鍵,默認(rèn)為主鍵索引

SELECT id FROM test LIMIT 9000000,100;

現(xiàn)在優(yōu)化的方案有兩種,即通過id作為查詢條件使用子查詢實(shí)現(xiàn)和使用join實(shí)現(xiàn);

1、id>=的(子查詢)形式實(shí)現(xiàn)

select * from test where id >= (select id from test limit 9000000,1)limit 0,100

使用join的形式;

SELECT * FROM test a JOIN (SELECT id FROM test LIMIT 9000000,100) b ON a.id = b.id

這兩種優(yōu)化查詢使用時(shí)間比較接近,其實(shí)兩者用的都是一個(gè)原理,所以效果也差不多。但個(gè)人建議最好使用join,盡量減少子查詢的使用。注:目前是千萬級(jí)別查詢,如果將至百萬級(jí)別,速度會(huì)更快。

SELECT * FROM test a JOIN (SELECT id FROM test LIMIT 1000000,100) b ON a.id = b.id

你用過MySQL那些存儲(chǔ)引擎

他們都有什么特點(diǎn)和區(qū)別?

這是高級(jí)開發(fā)者面試時(shí)經(jīng)常被問的問題。實(shí)際我們?cè)谄綍r(shí)的開發(fā)中,經(jīng)常會(huì)遇到的。Mysql的存儲(chǔ)引擎有這么多種,實(shí)際我們?cè)谄綍r(shí)用的最多的莫過于InnoDB和MyISAM了。所有如果面試官問道m(xù)ysql有哪些存儲(chǔ)引擎,你只需要告訴這兩個(gè)常用的就行。

那他們都有什么特點(diǎn)和區(qū)別呢?

MyISAM:默認(rèn)表類型,它是基于傳統(tǒng)的ISAM類型,ISAM是Indexed Sequential Access Method (有索引的順序訪問方法) 的縮寫,它是存儲(chǔ)記錄和文件的標(biāo)準(zhǔn)方法。不是事務(wù)安全的,而且不支持外鍵,如果執(zhí)行大量的select,insert MyISAM比較適合。

InnoDB:支持事務(wù)安全的引擎,支持外鍵、行鎖、事務(wù)是他的最大特點(diǎn)。如果有大量的update和insert,建議使用InnoDB,特別是針對(duì)多個(gè)并發(fā)和QPS較高的情況。注:在MySQL 5.5之前的版本中,默認(rèn)的搜索引擎是MyISAM,從MySQL 5.5之后的版本中,默認(rèn)的搜索引擎變更為InnoDB

MyISAM和InnoDB的區(qū)別

1.InnoDB支持事務(wù),MyISAM不支持。對(duì)于InnoDB每一條SQL語言都默認(rèn)封裝成事務(wù),自動(dòng)提交,這樣會(huì)影響速度,所以最好把多條SQL語言放在begin和commit之間,組成一個(gè)事務(wù);

2.InnoDB支持外鍵,而MyISAM不支持。

3.InnoDB是聚集索引,使用B+Tree作為索引結(jié)構(gòu),數(shù)據(jù)文件是和(主鍵)索引綁在一起的(表數(shù)據(jù)文件本身就是按B+Tree組織的一個(gè)索引結(jié)構(gòu)),必須要有主鍵,通過主鍵索引效率很高。MyISAM是非聚集索引,也是使用B+Tree作為索引結(jié)構(gòu),索引和數(shù)據(jù)文件是分離的,索引保存的是數(shù)據(jù)文件的指針。主鍵索引和輔助索引是獨(dú)立的。

4.InnoDB不保存表的具體行數(shù),執(zhí)行select count(*) from table時(shí)需要全表掃描。而MyISAM用一個(gè)變量保存了整個(gè)表的行數(shù),執(zhí)行上述語句時(shí)只需要讀出該變量即可,速度很快。

5.Innodb不支持全文索引,而MyISAM支持全文索引,查詢效率上MyISAM要高;5.7以后的InnoDB支持全文索引了。

6.InnoDB支持表、行級(jí)鎖(默認(rèn)),而MyISAM支持表級(jí)鎖。;

7.InnoDB表必須有主鍵(用戶沒有指定的話會(huì)自己找或生產(chǎn)一個(gè)主鍵),而Myisam可以沒有。

8.Innodb存儲(chǔ)文件有frm、ibd,而Myisam是frm、MYD、MYI。

9.Innodb:frm是表定義文件,ibd是數(shù)據(jù)文件。

10.Myisam:frm是表定義文件,myd是數(shù)據(jù)文件,myi是索引文件。

MySQL復(fù)雜查詢語句的優(yōu)化

說到復(fù)雜SQL優(yōu)化,最多的是由于多表關(guān)聯(lián)造成了大量的復(fù)雜的SQL語句,那我們拿到這種sql到底該怎么優(yōu)化呢,實(shí)際優(yōu)化也是有套路的,只要按照套路執(zhí)行就行。復(fù)雜SQL優(yōu)化方案:

1.使用EXPLAIN關(guān)鍵詞檢查SQL。EXPLAIN可以幫你分析你的查詢語句或是表結(jié)構(gòu)的性能瓶頸,就得EXPLAIN 的查詢結(jié)果還會(huì)告訴你你的索引主鍵被如何利用的,你的數(shù)據(jù)表是如何被搜索和排序的,是否有全表掃描等;

2.查詢的條件盡量使用索引字段,如某一個(gè)表有多個(gè)條件,就盡量使用復(fù)合索引查詢,復(fù)合索引使用要注意字段的先后順序。

3.多表關(guān)聯(lián)盡量用join,減少子查詢的使用。表的關(guān)聯(lián)字段如果能用主鍵就用主鍵,也就是盡可能的使用索引字段。如果關(guān)聯(lián)字段不是索引字段可以根據(jù)情況考慮添加索引。

4.盡量使用limit進(jìn)行分頁批量查詢,不要一次全部獲取。

5.絕對(duì)避免select *的使用,盡量select具體需要的字段,減少不必要字段的查詢;

6.盡量將or 轉(zhuǎn)換為 union all。

7.盡量避免使用is null或is not null。

8.要注意like的使用,前模糊和全模糊不會(huì)走索引。

9.Where后的查詢字段盡量減少使用函數(shù),因?yàn)楹瘮?shù)會(huì)造成索引失效。

10.避免使用不等于(!=),因?yàn)樗粫?huì)使用索引。

11.用exists代替in,not exists代替not in,效率會(huì)更好;

12.避免使用HAVING子句, HAVING 只會(huì)在檢索出所有記錄之后才對(duì)結(jié)果集進(jìn)行過濾,這個(gè)處理需要排序,總計(jì)等操作。如果能通過WHERE子句限制記錄的數(shù)目,那就能減少這方面的開銷。

13.千萬不要 ORDER BY RAND()

以上就是詳解MySQL數(shù)據(jù)庫千萬級(jí)數(shù)據(jù)查詢和存儲(chǔ)的詳細(xì)內(nèi)容,更多關(guān)于MySQL數(shù)據(jù)庫千萬級(jí)數(shù)據(jù)查詢和存儲(chǔ)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

您可能感興趣的文章:
  • .Net Core導(dǎo)入千萬級(jí)數(shù)據(jù)至Mysql的步驟
  • .Net Core導(dǎo)入千萬級(jí)數(shù)據(jù)至Mysql數(shù)據(jù)庫的實(shí)現(xiàn)方法
  • mysql千萬級(jí)數(shù)據(jù)量根據(jù)索引優(yōu)化查詢速度的實(shí)現(xiàn)
  • MySQL循環(huán)插入千萬級(jí)數(shù)據(jù)
  • MySQL 千萬級(jí)數(shù)據(jù)量如何快速分頁
  • mysql千萬級(jí)數(shù)據(jù)分頁查詢性能優(yōu)化
  • mysql千萬級(jí)數(shù)據(jù)大表該如何優(yōu)化?
  • MySQL單表千萬級(jí)數(shù)據(jù)處理的思路分享

標(biāo)簽:衡水 蘭州 湖南 湘潭 崇左 仙桃 黃山 銅川

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《詳解MySQL數(shù)據(jù)庫千萬級(jí)數(shù)據(jù)查詢和存儲(chǔ)》,本文關(guān)鍵詞  ;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 收縮
    • 微信客服
    • 微信二維碼
    • 電話咨詢

    • 400-1100-266