MySQL之數據庫優化

Mysql數據庫的優化技術mysql

對mysql優化是一個綜合性的技術,主要包括程序員

•表的設計合理化(符合3NF)算法

•添加適當索引(index) [四種: 普通索引、主鍵索引、惟一索引unique、全文索引]sql

•分表技術(水平分割、垂直分割)數據庫

•讀寫[寫: update/delete/add]分離編程

•存儲過程 [模塊化編程,能夠提升速度]windows

•對mysql配置優化 [配置最大併發數my.ini, 調整緩存大小 ]緩存

•mysql服務器硬件升級安全

•定時的去清除不須要的數據,定時進行碎片整理(MyISAM)服務器

數據庫優化工做

對於一個以數據爲中心的應用,數據庫的好壞直接影響到程序的性能,所以數據庫性能相當重要。通常來講,要保證數據庫的效率,要作好如下四個方面的工做:

① 數據庫設計

② sql語句優化

③ 數據庫參數配置

④ 恰當的硬件資源和操做系統

此外,使用適當的存儲過程,也能提高性能。

這個順序也表現了這四個工做對性能影響的大小

數據庫表設計

通俗地理解三個範式,對於數據庫設計大有好處。在數據庫設計中,爲了更好地應用三個範式,就必須通俗地理解三個範式(通

俗地理解是夠用的理解,並非最科學最準確的理解):

第一範式:1NF是對屬性的原子性約束,要求屬性(列)具備原子性,不可再分解;(只要是關係型數據庫都知足1NF)

第二範式:2NF是對記錄的唯一性約束,要求記錄有唯一標識,即實體的唯一性;

第三範式:3NF是對字段冗餘性的約束,它要求字段沒有冗餘。 沒有冗餘的數據庫設計能夠作到。

可是,沒有冗餘的數據庫未必是最好的數據庫,有時爲了提升運行效率,就必須下降範式標準,適當保留冗餘數據。具體作法是: 在概念數據模型設計時遵照第三範式,下降範式標準的工做放到物理數據模型設計時考慮。下降範式就是增長字段,容許冗餘。

☞ 數據庫的分類

關係型數據庫: mysql/oracle/db2/informix/sysbase/sql server

非關係型數據庫: (特色: 面向對象或者集合)

NoSql數據庫: MongoDB(特色是面向文檔)

舉例說明什麼是適度冗餘,或者說有理由的冗餘!

上面這個就是不合適的冗餘,緣由是:

在這裏,爲了提升學生活動記錄的檢索效率,把單位名稱冗餘到學生活動記錄表裏。單位信息有500條記錄,而學生活動記錄在

一年內大概有200萬數據量。 若是學生活動記錄表不冗餘這個單位名稱字段,只包含三個int字段和一個timestamp字段,只佔用了16字節,是一個很小的表。而冗餘了一個 varchar(32)的字段後則是原來的3倍,檢索起來相應也多了這麼多的I/O。並且記錄數相差懸殊,500 VS 2000000 ,致使更新一個單位名稱還要更新4000條冗餘記錄。因而可知,這個冗餘根本就是拔苗助長。

訂單表裏面的Price就是一個冗餘字段,由於咱們能夠從訂單明細表中統計出這個訂單的價格,可是這個冗餘是合理的,也能提高查詢性能。

從上面兩個例子中能夠得出一個結論:

1---n 冗餘應當發生在1這一方.

SQL語句優化

SQL優化的通常步驟

1.經過show status命令瞭解各類SQL的執行頻率。

2.定位執行效率較低的SQL語句-(重點select)

3.經過explain分析低效率的SQL

4.肯定問題並採起相應的優化措施

-- select語句分類
Select
Dml數據操做語言(insert update delete)
dtl 數據事物語言(commit rollback savepoint)
Ddl數據定義語言(create alter drop..)
Dcl(數據控制語言) grant revoke
-- Show status 經常使用命令
--查詢本次會話
Show session status like 'com_%'; //show session status like 'Com_select'
--查詢全局
Show global status like 'com_%';
-- 給某個用戶受權
grant all privileges on *.* to 'abc'@'%';
--爲何這樣受權 'abc'表示用戶名 '@' 表示host, 查看一下mysql->user表就知道了
--回收權限
revoke all on *.* from 'abc'@'%';
--刷新權限[也能夠不寫]
flush privileges; 

SQL語句優化-show參數

MySQL客戶端鏈接成功後,經過使用show [session|global] status 命令能夠提供服務器狀態信息。其中的session來表示當前的鏈接的統計結果,global來表示自數據庫上次啓動至今的統計結果。默認是session級別的。

下面的例子:

show status like 'Com_%';

其中Com_XXX表示XXX語句所執行的次數。

重點注意:Com_select,Com_insert,Com_update,Com_delete經過這幾個參數,能夠容易地瞭解到當前數據庫的應用是以插入更新爲主仍是以查詢操做爲主,以及各種的SQL大體的執行比例是多少。

還有幾個經常使用的參數便於用戶瞭解數據庫的基本狀況。

Connections:試圖鏈接MySQL服務器的次數

Uptime:服務器工做的時間(單位秒)

Slow_queries:慢查詢的次數 (默認是慢查詢時間10s)

show status like 'Connections'
show status like 'Uptime'
show status like 'Slow_queries' 

如何查詢mysql的慢查詢時間

Show variables like 'long_query_time'; 

修改mysql 慢查詢時間

set long_query_time=2 

SQL語句優化-定位慢查詢

問題是: 如何從一個大項目中,迅速的定位執行速度慢的語句. (定位慢查詢)

首先咱們瞭解mysql數據庫的一些運行狀態如何查詢(好比想知道當前mysql運行的時間/一共執行了多少次

select/update/delete.. / 當前鏈接)

爲了便於測試,咱們構建一個大表(400 萬)-> 使用存儲過程構建

默認狀況下,mysql認爲10秒纔是一個慢查詢.

修改mysql的慢查詢.

show variables like 'long_query_time' ; //能夠顯示當前慢查詢時間
set long_query_time=1 ;//能夠修改慢查詢時間 

構建大表->大表中記錄有要求, 記錄是不一樣纔有用,不然測試效果和真實的相差大.建立:

CREATE TABLE dept( /*部門表*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*編號*/
dname VARCHAR(20) NOT NULL DEFAULT "", /*名稱*/
loc VARCHAR(13) NOT NULL DEFAULT "" /*地點*/
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

CREATE TABLE emp
(empno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0, /*編號*/
ename VARCHAR(20) NOT NULL DEFAULT "", /*名字*/
job VARCHAR(9) NOT NULL DEFAULT "",/*工做*/
mgr MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,/*上級編號*/
hiredate DATE NOT NULL,/*入職時間*/
sal DECIMAL(7,2) NOT NULL,/*薪水*/
comm DECIMAL(7,2) NOT NULL,/*紅利*/
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0 /*部門編號*/
)ENGINE=MyISAM DEFAULT CHARSET=utf8 ;

CREATE TABLE salgrade
(
grade MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
losal DECIMAL(17,2) NOT NULL,
hisal DECIMAL(17,2) NOT NULL
)ENGINE=MyISAM DEFAULT CHARSET=utf8; 

測試數據

INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999); 

爲了存儲過程可以正常執行,咱們須要把命令執行結束符修改delimiter $$
建立函數,該函數會返回一個指定長度的隨機字符串

create function rand_string(n INT) 
returns varchar(255) #該函數會返回一個字符串
begin 
#chars_str定義一個變量 chars_str,類型是 varchar(100),默認值'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
declare chars_str varchar(100) default
'abcdefghijklmnopqrstuvwxyzABCDEFJHIJKLMNOPQRSTUVWXYZ';
declare return_str varchar(255) default '';
declare i int default 0;
while i < n do 
set return_str =concat(return_str,substring(chars_str,floor(1+rand()*52),1));
set i = i + 1;
end while;
return return_str;
end 

建立一個存儲過程

create procedure insert_emp(in start int(10),in max_num int(10))
begin
declare i int default 0; 
#set autocommit =0 把autocommit設置成0
set autocommit = 0; 
repeat
set i = i + 1;
insert into emp values ((start+i) ,rand_string(6),'SALESMAN',0001,curdate(),2000,400,rand());
until i = max_num
end repeat;
commit;
end 
#調用剛剛寫好的函數, 1800000條記錄,從100001號開始
call insert_emp(100001,4000000);

這時咱們若是出現一條語句執行時間超過1秒中,就會統計到.

若是把慢查詢的sql記錄到咱們的一個日誌中

在默認狀況下,低版本的mysql不會記錄慢查詢,須要在啓動mysql時候,指定記錄慢查詢才能夠

bin\mysqld.exe - -safe-mode - -slow-query-log [mysql5.5 能夠在my.ini指定]

bin\mysqld.exe –log-slow-queries=d:/abc.log [低版本mysql5.0能夠在my.ini指定]

該慢查詢日誌會放在data目錄下[在mysql5.0這個版本中時放在 mysql安裝目錄/data/下],在 mysql5.5.19下是須要查看

my.ini 的 datadir="C:/Documents and Settings/All Users/Application Data/MySQL/MySQL Server 5.5/Data/「來肯定.

在mysql5.6中,默認是啓動記錄慢查詢的,my.ini的所在目錄爲:C:\ProgramData\MySQL\MySQL Server 5.6,其中有一個配置項

slow-query-log=1

針對 mysql5.5啓動慢查詢有兩種方法

bin\mysqld.exe - -safe-mode - -slow-query-log

也能夠在my.ini 文件中配置:

[mysqld]
# The TCP/IP Port the MySQL Server will listen on
port=3306
slow-query-log 

經過慢查詢日誌定位執行效率較低的SQL語句。慢查詢日誌記錄了全部執行時間超過long_query_time所設置的SQL語句。

show variables like 'long_query_time';
set long_query_time=2;

爲dept表添加數據

desc dept;
ALTER table dept add id int PRIMARY key auto_increment;
CREATE PRIMARY KEY on dept(id);
create INDEX idx_dptno_dptname on dept(deptno,dname);
INSERT into dept(deptno,dname,loc) values(1,'研發部','康和盛大廈5樓501');
INSERT into dept(deptno,dname,loc) values(2,'產品部','康和盛大廈5樓502');
INSERT into dept(deptno,dname,loc) values(3,'財務部','康和盛大廈5樓503');UPDATE emp set deptno=1 where empno=100002;

****測試語句***[對emp表的記錄能夠爲3600000 ,效果很明顯慢]

select * from emp where empno=(select empno from emp where ename='研發部')

若是帶上order by e.empno 速度就會更慢,有時會到1min多.

測試語句

select * from emp e,dept d where e.empno=100002 and e.deptno=d.deptno; 

查看慢查詢日誌:默認爲數據目錄data中的host-name-slow.log。低版本的mysql須要經過在開啓mysql時使用- -log-slow-queries[=file_name]來配置

SQL語句優化-explain分析問題

Explain select * from emp where ename=「wsrcla」

會產生以下信息:

select_type:表示查詢的類型。

table:輸出結果集的表

type:表示表的鏈接類型

possible_keys:表示查詢時,可能使用的索引

key:表示實際使用的索引

key_len:索引字段的長度

rows:掃描出的行數(估算的行數)

Extra:執行狀況的描述和說明

explain select * from emp where ename='JKLOIP'

若是要測試Extra的filesort能夠對上面的語句修改

explain select * from emp order by ename\G 

EXPLAIN詳解

id

SELECT識別符。這是SELECT的查詢序列號

id 示例

SELECT * FROM emp WHERE empno = 1 and ename = (SELECT ename FROM emp WHERE empno = 100001) \G; 

select_type

PRIMARY :子查詢中最外層查詢

SUBQUERY : 子查詢內層第一個SELECT,結果不依賴於外部查詢

DEPENDENT SUBQUERY:子查詢內層第一個SELECT,依賴於外部查詢

UNION :UNION語句中第二個SELECT開始後面全部SELECT,

SIMPLE

UNION RESULT UNION 中合併結果

Table

顯示這一步所訪問數據庫中表名稱

Type

對錶訪問方式

ALL:

SELECT * FROM emp \G

完整的表掃描 一般很差

SELECT * FROM (SELECT * FROM emp WHERE empno = 1) a ;

system:表僅有一行(=系統表)。這是const聯接類型的一個特

const:表最多有一個匹配行

Possible_keys

該查詢能夠利用的索引,若是沒有任何索引顯示 null

Key

Mysql 從 Possible_keys 所選擇使用索引

Rows

估算出結果集行數

Extra

查詢細節信息

No tables :Query語句中使用FROM DUAL 或不含任何FROM子句

Using filesort :當Query中包含 ORDER BY 操做,並且沒法利用索引完成排序,

Impossible WHERE noticed after reading const tables: MYSQL Query Optimizer

經過收集統計信息不可能存在結果

Using temporary:某些操做必須使用臨時表,常見 GROUP BY ; ORDER BY

Using where:不用讀取表中全部信息,僅經過索引就能夠獲取所需數據;

創建適當的索引

提及提升數據庫性能,索引是最物美價廉的東西了。不用加內存,不用改程序,不用調sql,只要執行個正確的'create index',查詢速度就可能提升百倍千倍,這可真有誘惑力。但是天下沒有免費的午飯,查詢速度的提升是以插入、更新、刪除的速度爲代價的,這些寫操做,增長了大量的I/O。

是否是創建一個索引就能解決全部的問題?ename上沒有創建索引會怎樣?

select * from emp where ename='研發部'; 

---測試案例命令以下 (最好以 select * from emp e,dept d where e.empno=123451 )

*添加主鍵

ALTER TABLE emp ADD PRIMARY KEY(empno); 

*刪除主鍵

alter table emp drop primary key; 

索引的原理說明

沒有索引爲何會慢?

使用索引爲何會快?

索引的代價

一、磁盤佔用

二、對dml(update delete insert)語句的效率影響

btree 方式檢索,算法複雜度: log2N 次數

 

哪些列上適合添加索引

一、較頻繁的做爲查詢條件字段應該建立索引

select * from emp where empno = 1; 

二、惟一性太差的字段不適合單首創建索引,即便頻繁做爲查詢條件

select * from emp where sex = '男' 

三、更新很是頻繁的字段不適合建立索引

select * from emp where logincount = 1 

四、不會出如今WHERE子句中的字段不應建立索引

索引的類型

•主鍵索引,主鍵自動的爲主索引 (類型Primary)

•惟一索引 (UNIQUE)

•普通索引 (INDEX)

•全文索引 (FULLTEXT) [適用於MyISAM] ——》sphinx + 中文分詞 coreseek [sphinx 的中文版 ]

•綜合使用=>複合索引

簡述mysql四種索引的區別

lPRIMARY 索引 =》在主鍵上自動建立

lUNIQUE 索引=> 只要是UNiQUE 就是Unique索引.(只能在字段內容不重複的狀況下,才能建立惟一索引)

lINDEX 索引=>就是普通索引

lFULLTEXT => 只在MYISAM 存儲引擎支持, 目的是全文索引,在內容系統中用的多, 在全英文網站用多(英文詞獨立). 中文數據不經常使用,意義不大,國內全文索引一般使用 sphinx來完成,全文索引只能在 char varchar text字段建立.

全文索引案例

1.建立表

create table news(id int , title varchar(32),con varchar(1024)) engine=MyISAM; 

2.創建全文索引

create fulltext index ful_inx on news (con); 

3.插入數據

這裏要注意,對於常見的英文 fulltext 不會匹配,並且插入的語句自己是正確的.

'but it often happens that they are not above supporting themselves by dishonest means.which should be more disreputable.Cultivate poverty like a garden herb'

4.看看匹配度

mysql> select match(con) against('poverty') from news;
+-------------------------------+
| match(con) against('poverty') |
+-------------------------------+
| 0 |
| 0 |
| 0 |
| 0.9853024482727051 |
+------------------------------+ 

0表示沒有匹配到,或者你的詞是中止詞,是不會創建索引的.

使用全文索引,不能使用like語句,這樣就不會使用到全文索引了.

複合索引

create index 索引名 on 表名(列1,列2); 

索引的使用

創建索引

create [UNIQUE|FULLTEXT] index index_name on tbl_name (col_name [(length)] [ASC | DESC] , …..);
alter table table_name ADD INDEX [index_name] (index_col_name,...) 
添加主鍵(索引) ALTER TABLE 表名 ADD PRIMARY KEY(列名,..); 聯合主鍵

刪除索引

DROP INDEX index_name ON tbl_name;
alter table table_name drop index index_name; 
刪除主鍵(索引)比較特別: alter table t_b drop primary key;

查詢索引(都可)

show index(es) from table_name;
show keys from table_name;
desc table_Name; 

修改索引,咱們通常是先刪除在從新建立.

查詢要使用索引最重要的條件是查詢條件中須要使用索引。

下列幾種狀況下有可能使用到索引:

1,對於建立的多列索引,只要查詢條件使用了最左邊的列,索引通常就會被使用。

2,對於使用like的查詢,查詢若是是 '%aaa' 不會使用到索引, 'aaa%' 會使用到索引。

下列的表將不使用索引:

1,若是條件中有or,即便其中有條件帶索引也不會使用。

2,對於多列索引,不是使用的第一部分,則不會使用索引。

3,like查詢是以%開頭

4,若是列類型是字符串,那必定要在條件中將數據使用引號引用起來。不然不使用索引。(添加時,字符串必須'')

5,若是mysql估計使用全表掃描要比使用索引快,則不使用索引。

測試案例(就在前面的dept表上作演示.)

CREATE TABLE dept(
deptno MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
dname VARCHAR(20) NOT NULL DEFAULT "",
loc VARCHAR(13) NOT NULL DEFAULT ""
) ENGINE=MyISAM DEFAULT CHARSET=utf8 ; 
--放入數據,前面應該已經添加了,若是沒有則須要從新添加
--測試開始.

添加一個主鍵索引

alter table dept add primary key (deptno) 

--測試語句

explain select * from dept where deptno=1; 

結果是:

mysql> explain select * from dept where deptno=1;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: dept
type: const
possible_keys: PRIMARY
key: PRIMARY
key_len: 3
ref: const
rows: 1
Extra:
1 row in set (0.00 sec) 

--建立多列索引

alter table dept add index myind (dname,loc); 

--證實對於建立的多列索引,只要查詢條件使用了最左邊的列,索引通常就會被使用

explain select * from dept where dname='研發部'; 會顯示使用到了索引myind
explain select * from dept where loc='MsBDpMRX'; 不會顯示使用到了索引myind

--對於使用like的查詢

explain select * from dept where dname like '%研發部'; 不會顯示使用到了索引myind
explain select * from dept where dname like '研發部%'; 會顯示使用到了索引myind

--若是條件中有or,即便其中有條件帶索引也不會使用

--爲了演示,咱們把複合索引刪除,而後只在dname上加入索引.

alter table dept drop index myind
alter table dept add index myind (dname)
explain select * from dept where dname='研發部' or loc='aa';-- 就不會使用到dname列上的 

--若是列類型是字符串,那必定要在條件中將數據使用引號引用起來。不然不使用索引

select * from dept from dname=1234; //不會使用到索引
select * from dept from dname='1234'; //會使用到索引

查看索引的使用狀況

show status like 'Handler_read%';

你們能夠注意:

handler_read_key:這個值越高越好,越高表示使用索引查詢到的次數。

handler_read_rnd_next:這個值越高,說明查詢低效。

* 這時咱們會看到handler_read_rnd_next值很高,爲何,這是由於咱們前面沒有加索引的時候,作過屢次查詢的緣由.

經常使用SQL優化

大批量插入數據(MySql管理員) 瞭解

對於MyISAM:

alter table table_name disable keys;
loading data//insert語句;
alter table table_name enable keys; 

對於Innodb:

1,將要導入的數據按照主鍵排序

2,set unique_checks=0,關閉惟一性校驗。

3,set autocommit=0,關閉自動提交。

優化group by 語句

默認狀況,MySQL對全部的group by col1,col2進行排序。這與在查詢中指定order by col1, col2相似。若是查詢中包括group by但用戶想要避免排序結果的消耗,則可使用order by

null禁止排序

有些狀況下,可使用鏈接來替代子查詢。

由於使用join,MySQL不須要在內存中建立臨時表。(講解)

若是想要在含有or的查詢語句中利用索引,則or之間的每一個條件列都必須用到索引,若是沒有索引,則應該考慮增長索引(與環境相關 講解)

select * from 表名 where 條件1='' or 條件2='tt'
explaine select * from dept group by dname; =>這時顯示 extra: using filesort 說明會進行排序
explaine select * from dept group by dname order by null =>這時不含有顯示 extra: using filesort 說明不會進行排序

***有些狀況下,可使用鏈接來替代子查詢。由於使用join,MySQL不須要在內存中建立臨時表

explain select * from emp , dept where emp.deptno=dept.deptno;

和下面比較就能夠說明問題!!

explain select * from emp left join dept on emp.deptno=dept.deptno;

選擇合適的存儲引擎

MyISAM:默認的MySQL存儲引擎。若是應用是以讀操做和插入操做爲主,只有不多的更新和刪除操做,而且對事務的完整性要求不是很高。其優點是訪問的速度快。

InnoDB:提供了具備提交、回滾和崩潰恢復能力的事務安全。可是對比MyISAM,寫的處理效率差一些而且會佔用更多的磁盤空間。

Memory:數據存在內存中,服務重啓時,數據丟失

MyISAM: 在插入數據時,默認放在最後. ,刪除數據後,空間不回收.(不支持事務和外鍵)

InnoDB 支持事務和外鍵

對應咱們程序員說,經常使用的存儲引擎主要是 myisam / innodb / memory,heap 表

若是選用小原則:

1.若是追求速度,不在意數據是否一直把保存,也不考慮事務,請選擇 memory 好比存放用戶在線狀態.

2.若是表的數據要持久保存,應用是以讀操做和插入操做爲主,只有不多的更新和刪除操做,而且對事務的完整性要求不是很高。選用MyISAM

3.若是須要數據持久保存,並提供了具備提交、回滾和崩潰恢復能力的事務安全,請選用Innodb

選擇合適的數據類型

在精度要求高的應用中,建議使用定點數來存儲數值,以保證結果的準確性。deciaml 不要用float

對於存儲引擎是MyISAM的數據庫,若是常常作刪除和修改記錄的操做,要定時執行optimize table table_name;功能對錶進行碎片整理。

日期類型要根據實際須要選擇可以知足應用的最小存儲的早期類型

create table bbs(id int ,con varchar(1024) , pub_time int);
date('Ymd',時間-3*24*60*60); 2038年-1-19

對於使用浮點數和定點數的案例說明

create table temp1( t1 float(10,2), t2 decimal(10,2));
insert into temp1 values(1000000.32,1000000,32); 發現 t1 成了 1000000.31 因此有問題.

對於optimize table 表名 演示

create table temp2( id int) engine=MyISAM;
insert into temp2 values(1); insert into temp2 values(2); insert into temp2 values(3);
insert into temp2 select * from temp2;--複製
delete from temp2 where id=1; 發現 該表對於的數據文件沒有變小

按期執行 optimize table temp2 發現表大小變化,碎片整理完畢

&&對於InnoDB它的數據會存在data/ibdata1目錄下,在data/數據庫/只有一個 *.frm表結構文件.

 

對錶進行水平劃分          

若是一個表的記錄數太多了,好比上千萬條,並且須要常常檢索,那麼咱們就有必要化整爲零了。若是我拆成100個表,那麼每一個表只有10萬條記錄。固然這須要數據在邏輯上能夠劃分。一個好的劃分依據,有利於程序的簡單實現,也能夠充分利用水平分表的優點。好比系統界面上只提供按月查詢的功能,那麼把表按月拆分紅12個,每一個查詢只查詢一個表就夠了。若是非要按照地域來分,即便把表拆的再小,查詢仍是要聯合全部表來查,還不如不拆了。因此一個好的拆分依據是 最重要的。關鍵字:UNION

例:

  • 訂單表根據訂單產生時間來分表(一年一張)
  • 學生狀況表
  • 查詢電話費,近三個月的數據放入一張表,一年內的放入到另外一張表

對錶進行垂直劃分 

有些表記錄數並很少,可能也就二、3萬條,可是字段卻很長,表佔用空間很大,檢索表時須要執行大量I/O,嚴重下降了性能。這個時候須要把大的字段拆分到另外一個表,而且該表與原表是一對一的關係。 (JOIN)       

【試題內容】、【答案信息】兩個表,最初是做爲幾個字段添加到【試題信息】裏的,能夠看到試題內容和答案這兩個字段很長,在表裏有3萬記錄時,表已經佔 了1G的空間,在列試題列表時很是慢。通過分析,發現系統不少時候是根據【冊】、【單元】、類型、類別、難易程度等查詢條件,分頁顯示試題詳細內容。而每 次檢索都是這幾個表作join,每次要掃描一遍1G的表。咱們徹底能夠把內容和答案拆分紅另外一個表,只有顯示詳細內容的時候纔讀這個大表,由此 就產生了【試題內容】、【答案信息】兩個表。

選擇適當的字段類型,特別是主鍵     

選擇字段的通常原則是保小不保大,能用佔用字節小的字段就不用大字段。好比主鍵, 建議使用自增類型,這樣省空間,空間就是效率!按4個字節和按32個字節定位一條記錄,誰快誰慢太明顯了。涉及到幾個表作join時,效果就更明顯了。

文件、圖片等大文件用文件系統存儲

數據庫只存儲路徑。圖片和文件存放在文件系統,甚至單獨放在一臺服務器(圖牀 / 視頻服務器 ).

數據庫參數配置

最重要的參數就是內存,咱們主要用的innodb引擎,因此下面兩個參數調的很大

innodb_additional_mem_pool_size = 64M
innodb_buffer_pool_size =1G

對於myisam,須要調整key_buffer_size,固然調整參數仍是要看狀態,用show status語句能夠看到當前狀態,以決定改調整哪些參數

在my.ini修改端口3306,默認存儲引擎和最大鏈接數

在my.ini中.
port=3306 [有兩個地方修改]
default-storage-engine=INNODB 
max_connections=100

合理的硬件資源和操做系統

若是你的機器內存超過4G,那麼毋庸置疑應當採用64位操做系統和64位mysql 5.5.19 or mysql5.6

讀寫分離

    若是數據庫壓力很大,一臺機器支撐不了,那麼能夠用mysql複製實現多臺機器同步,將數據庫的壓力分散。

    Master
  Slave1
  Slave2
  Slave3

主庫master用來寫入,slave1—slave3都用來作select,每一個數據庫分擔的壓力小了不少。
要實現這種方式,須要程序特別設計,寫都操做master,讀都操做slave,給程序開發帶來了額外負擔。固然目前已經有中間件來實現這個代理,對程 序來讀寫哪些數據庫是透明的。官方有個mysql-proxy,可是仍是alpha版本的。新浪有個amobe for mysql,也可達到這個目的,結構以下

定時完成數據庫的備份

項目實際需求,請完成定時備份某個數據庫,或者定時備份數據庫的某些表的操做

windows 下每隔1小時,備份一次數據newsdb

windows 天天晚上2:00   備份 newsdb 下 某一張表

cmd> mysqldump –u root –p密碼  數據庫名 > 把數據庫放入到某個目錄

案例,備份 mydb 庫的全部表

進入mysqldump所在的目錄

cmd> mysqldump –u root –phsp shop> d:/shop.log   [把shop數據庫的全部表所有導出]

cmd> mysqldump –u root –phsp shop temusers emp > d:/shop2.log [shop數據庫的 temusers和emp導出]

如何恢復數據的表

進入的mysql操做界面

mysql>source  備份文件的全路徑

定時備份:(把命令寫入到my.bat 問中)

windows 如何定時備份 (天天凌晨2:00)

使用windows自帶的計劃任務,定時執行批處理命令。

增量備份和還原

定義:mysql數據庫會以二進制的形式,自動把用戶對mysql數據庫的操做,記錄到文件,當用戶但願恢復的時候,可使用備份文件進行恢復。

增量備份會記錄dml語句、建立表的語句,不會記錄select。記錄的東西包括:sql語句自己、操做時間,位置

進行增量備份的步驟和恢復

注意:mysql5.0及以前的版本是不支持增量備份的

一、配置my.ini文件或者my.conf,啓用二進制備份。

打開my.ini文件,查找log-bin,進行配置:log-bin=G:\Database\mysqlbinlog\mylog

在G:\Database目錄下面新建目錄mysqlbinlog

二、重啓mysql服務

這個時候會在mysqlbinlog目錄下面看到如下兩個文件:

mylog.000001:日誌備份文件。若是要查看這個日誌文件裏面的信息,咱們可使用mysqlbinlog程序查看,mysqlbinlog程序存放在mysql的bin目錄下面(「C:\Program Files\MySQL\MySQL Server 5.6\bin」)。

執行sql語句

UPDATE emp set ename='zouqj' where empno=100003;

開始——運行——cmd,mysqlbinlog 備份文件路徑

C:\Program Files\MySQL\MySQL Server 5.6\bin>mysqlbinlog G:\Database\mysqlbinlog\mylog.000001

mylog.index:日誌索引文件,裏面記錄了因此的日誌文件。(G:\Database\mysqlbinlog\mylog.000001)

三、假設如今問題來了,我這條update是誤操做,如何進行恢復

在mysql日誌中會記錄每一次操做的時間和位置,因此咱們既能夠根據時間來恢復,也能夠根據位置來恢復。

那麼,咱們如今立刻能夠從上圖看出,這條語句產生的時間是"2016-04-17 12:01:36",位置是614

按時間來恢復

咱們能夠選擇在語句產生時間的前一秒

執行cmd命令:mysqlbinlog --stop-datetime="2016-04-17 12:01:35" G:\Database\mysqlbinlog\mylog.000001 | mysql -uroot -p

這個時候我再執行SQL語句查看

SELECT * from emp where empno=100003;

結果變成了

按位置來恢復

執行cmd命令:mysqlbinlog --stop-position="614" G:\Database\mysqlbinlog\mylog.000001 | mysql -uroot -p

這個時候再執行SQL來查看結果,又變回來了。

 

MySQL 增量備份與還原

相關文章
相關標籤/搜索