MySQL大數據的優化以及分解存儲

            MySQL大數據的優化以及分解存儲

前言:在上一章介紹了MySQL的優化以及優化的思路,那麼如果有一種情況如果數據庫已經建立好了索引,在使用sql語句索引查詢時;但是在慢查詢日誌當中任然找到了之前的sql語句會有哪幾種情況:

1):sql語句的索引沒有起到效果,

2):查詢的數據量過大,造成數據的查詢緩慢,

在工作當中每個數據庫都會存在龐大的數據量,比如說訪問量等等都會造成數據的查詢緩慢,那麼如何解決這個問題,接下來往下看:

分區和分表:

我們的數據庫數據越來越大,隨之而來的是單個表中數據太多。以至於查詢書讀變慢,而且由於表的鎖機制導致應用操作也搜到嚴重影響,出現了數據庫性能瓶頸。

 

1、分表

什麼是分表?

分表是將一個大表按照一定的規則分解成多張具有獨立存儲空間的實體表,每個表都對應三個文件,MYD數據文件,.MYI索引文件,.frm表結構文件。這些表可以分佈在同一塊磁盤上,也可以在不同的機器上。app讀寫的時候根據事先定義好的規則得到對應的表名,然後去操作它。主要針對myisam存儲,如果是innodb存儲那麼將會是.idb文件和.frm文件

將單個數據庫表進行拆分,拆分成多個數據表,然後用戶訪問的時候,根據一定的算法(hash的方式,可以用求餘(取模)的方式),讓用戶訪問不同的表,這樣數據分散到多個數據表中,減少了單個數據表的訪問壓力。提升了數據庫訪問性能。分表的目的就在於此,減小數據庫的負擔,縮短查詢時間。

注:客戶端訪問的時候根本不知道表已經被分開了,任然屬於一個邏輯的整體對於客戶端來說,客戶端主要關心的是查詢的內容以及查詢的速度效率,但是作爲一名DBA必須要了解這些;只有這樣才能夠滿足客戶的要求。

 

另外在分表的時候分爲兩種;垂直分割和水平分割:

垂直切分是指數據表列的拆分,把一張列比較多的表拆分爲多張表

水平拆分是指數據錶行的拆分,把一張的表的數據拆成多張表來存放。

 

分表的方式:

1mysql集羣

它並不是分表,但起到了和分表相同的作用。集羣可分擔數據庫的操作次數,將任務分擔到多臺數據庫上。集羣可以讀寫分離,減少讀寫壓力。從而提升數據庫性能。

2)預先估計會出現大數據量並且訪問頻繁的表,將其分爲若干個表

比如說娛樂新聞的app可以通過每一分鐘的訪問量,推算出每個小時,以及每一天的大概訪問情況,如果是這樣的話,那麼我們就以分表存儲這些數據,例如創建10000張表,設定好閾值,當一定的數據量達到預先設定的值得時候就想下一個表當中存儲內容,保證數據庫的性能。

3)利用merge存儲引擎來實現分表

對於DBA來說,如果要把已有的大數據量表分開比較痛苦,最痛苦的事就是改代碼,因爲程序裏面的sql語句已經寫好了,用merge存儲引擎來實現分表, 這種方法比較適合。

 

那麼我們來介紹下merge的用法以及功能:

merge存儲引擎:

merge分表,分爲主表和子表,主表類似於一個殼子,邏輯上封裝了子表,實際上數據都是存儲在子表中的。

注:字表是用來存放真實數據的地方是不能在進行細分的,但是可以合併,如果要創建多個字表,就在開始創建的時候多創建幾個,進行估算大概需要幾個。

 

我們可以通過主表插入和查詢數據,如果清楚分表規律,也可以直接操作子表。

那麼我們來對merge進行一個演示,希望大家對merge有一個更加深刻的瞭解

 

創建一個完整表存儲着所有的成員信息(表名爲tty

mysql> drop database IF EXISTS test;   =======>如果test存在那麼就刪掉它

mysql> create database test=========>創建test數據庫

mysql> use test;                     ==========>進入test

create table tty(             ==============>創建tty

id bigint auto_increment primary key, ============> id號設置爲主鍵

name varchar(20),              =============>name的字符類型

sextinyint not nulldefault '0'        ==========>性別的字符類型

)engine=myisam default charset=utf8 auto_increment=1; ===========> 存儲引擎爲myisamutf-8字符集,可以自動擴展。

wKiom1lJxy2BmhZ5AAAzo_GJRxk173.png-wh_50 

接下來往裏面添加點數據:

mysql> insert into tty(name,sex) values('tom1',1);

mysql> insert into tty(name,sex) select name,sex from tty;

第二條語句多執行幾次就有了很多數據

 

wKiom1lJygryYRNiAAAZnyH4LqI701.png-wh_50 

執行之後我們來查詢一下有多少條數據:

mysql> select * from tty;    {8192條數據}

wKiom1lJyjjxraMUAAAPNteVSa8483.png-wh_50 

下面我們進行分表,這裏我們把tty分兩個表tb_tty1,tb_tty2

創建tb_tty1表:

mysql> use test;

DROP table IF EXISTS tb_tty1;

create table tb_tty1(

id bigint primary key ,

name varchar(20),

sex tinyint not null default '0'

)ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

wKiom1lJynjRnCK-AAAebOQmffY243.png-wh_50 

 

DROP table IF EXISTS tb_tty2;

create  table tb_tty2(

id bigint primary key,

name varchar(20),

sex tinyint not null default '0'

)ENGINE=MyISAM DEFAULT CHARSET=utf8;

創建tb_tty2

wKiom1lJytXCoeD6AAAa9HAHQWw844.png-wh_50 

//創建tb_tty2也可以用下面的語句  create table tb_tty2 like tb_tty1;

創建主表tb_tty

DROP table IF EXISTS tb_tty;
wKioL1lJyzPxDVQJAAAlGCKRMCw595.png

 

注:INSERT_METHOD,此參數INSERT_METHOD = NO 表示該表不能做任何寫入操作只作爲查詢使用,INSERT_METHOD = LAST表示插入到最後的一張表裏面。INSERT_METHOD = first表示插入到第一張表裏面。

 

 

查看一下tb_tty表、tb_tty1tb_tty2的結構:

mysql>desc tb_tty;

wKiom1lJy3zjeHiKAABdnGU9-oo332.png-wh_50 

接下來,我們把數據分到兩個分表中去:

mysql> insert into tb_tty1(id,name,sex) select id,name,sex from tty where id%2=0;

mysql> insert into tb_tty2(id,name,sex) select id,name,sex from tty where id%2=1;

如果要是分爲三個表的情況可以使用ID%3=0ID%3=1id%=2

wKiom1lJy7ySmAnFAAAgSdMt0tw958.png 

查看兩個子表的數據:{前面說過共有8192條數據}

wKioL1lJy-vgKaSXAAAOhPyjyJ8886.png-wh_50 

wKiom1lJzBvRUItaAAAPWkTcwTA758.png-wh_50 

 

注意:總表只是一個外殼,存取數據發生在一個一個的子表裏面。

注意:每個子表都有自已獨立的相關表文件,而主表只是一個殼,並沒有完整的相關表文件

wKioL1lJzHaCJy2JAABQhe2qnMM223.png-wh_50 

 

 

2、分區

什麼是分區?

分區和分表相似,都是按照規則分解表。不同在於分表將大表分解爲若干個獨立的實體表,分區是將數據分段劃分在多個位置存放,分區後,表還是一張表,但數據散列到多個位置。

另外分區也可以分爲兩種:

垂直分區和水平分區

水平分區Horizontal Partitioning)這種形式分區是對錶的行進行分區,所有在表中定義的列在每個數據集中都能找到,所以表的特性依然得以保持。

垂直分區Vertical Partitioning)這種分區方式一般來說是通過對錶的垂直劃分來減少目標表的寬度,使某些特定的列被劃分到特定的分區,每個分區都包含了其中的列所對應的行。

 

查看當將配置是否支持分區:

mysql> show plugins;

 

在顯示結果中,可以看到partitionACTIVE的,表示支持分區

wKioL1lJzK2wGNiZAAANIsPwMiU768.png 

之前演示了一個分表的方式,接下來爲大家演示一個分區的方式:

mysql> create database test2;

mysql> use test2;

mysql> create table if not exists user (

    id int not null auto_increment,

    name varchar(30) not null default ' ',

    sex int(1) not null default '0',

    primary key(id)

 )default charset=utf8 auto_increment=1

    partition by range(id) (

    partition p0 values less than (3),

    partition p1 values less than (6),

    partition p2 values less than (9),

    partition p3 values less than (12),

    partition p4 values less than maxvalue

);

wKioL1lJzN_TFK74AAAy8AATUJw697.png-wh_50 

 

插入些數據

mysql> insert into test2.user(name,sex)values ('tom1','0');

mysql> insert into test2.user(name,sex)values ('tom2','1');

mysql> insert into test2.user(name,sex)values ('tom3','1');

mysql> insert into test2.user(name,sex)values ('tom4','0');

mysql> insert into test2.user(name,sex)values ('tom5','0');

mysql> insert into test2.user(name,sex)values ('tom6','1');

mysql> insert into test2.user(name,sex)values ('tom7','1');

mysql> insert into test2.user(name,sex)values ('tom8','1');

mysql> insert into test2.user(name,sex)values ('tom9','1');

mysql> insert into test2.user(name,sex)values ('tom10','1');

mysql> insert into test2.user(name,sex)values ('tom11','1');

mysql> insert into test2.user(name,sex)values ('tom12','1');

mysql> insert into test2.user(name,sex)values ('tom13','1');

mysql> insert into test2.user(name,sex)values ('tom14','1');

 

到存放數據庫表文件的地方看一下

wKioL1lJzTWyiaKvAAAYIzPtT4Y037.png 

通過命令:

mysql> select count(id) as count from user;

wKiom1lJzWORiDYVAAALsaShnB4774.png-wh_50 

information_schema系統庫中的partitions表中查看分區信息

 wKioL1lJzZKBovXjAABZVoKiqrM708.png-wh_50 wKioL1lJzengPBoBAABP3YSO48A544.png-wh_50 wKioL1lJzijBG2GtAABUEtBQlCQ075.png-wh_50 wKioL1lJzlWAdMQ-AABXaCurNrs100.png-wh_50 wKiom1lJzn3RONkCAABY8SLXa7s173.png-wh_50

 

從某個分區中查詢數據

mysql> select * from test2.user partition(p0);

 

wKiom1lJzq2jdP5xAAAN9-dVLao127.png-wh_50 

新增分區

mysql> alter table test2.user add partition (partition partionname values less than (n));

使用此命令的時候需要的將p5刪掉之後纔可以進行新的增加

 

刪除分區
當刪除了一個分區,也同時刪除了該分區中所有的數據。
wKiom1lJztaSjFKqAAANa_KB2Lw033.png-wh_50

分區的合併
下面的SQL,將p1  p3合併爲2個分區p01 p02

mysql> alter table test2.user

    -> reorganize partition p1,p2,p3 into

    -> (partition p01 values less than (8),

    ->partition p02 values less than (12)

    -> );

後續爲大家繼續講解有關於mysql大數據的分解存儲方式以及思路,如果有不全的地方可以評論。。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章