mysql優(yōu)化

Mysql數(shù)據(jù)庫的優(yōu)化技術(shù)

對mysql優(yōu)化時(shí)一個(gè)綜合性的技術(shù),主要包括

a:表的設(shè)計(jì)合理化(符合3NF)

b:添加適當(dāng)索引(index) [四種:普通索引、主鍵索引、唯一索引unique、全文索引]

c:分表技術(shù)(水平分割、垂直分割)

d:讀寫[寫:

update/delete/add]分離

e:存儲過程[模塊化編程,可以提高速度]

f:對mysql配置優(yōu)化[配置最大并發(fā)數(shù)my.ini,調(diào)整緩存大小]

g: mysql服務(wù)器硬件升級

h:定時(shí)的去清除不需要的數(shù)據(jù),定時(shí)進(jìn)行碎片整理(MyISAM)

u什么樣的表才是符合3NF (范式)

數(shù)據(jù)庫參數(shù)配置:


INNODB 重要優(yōu)化設(shè)置【解決慢卡的問題】

1.內(nèi)存利用方面:

innodb_buffer_pool_size

這個(gè)參數(shù)和MyISAM的key_buffer_size有相似之處,但也是有差別的。這個(gè)參數(shù)主要緩存

innodb表的索引,數(shù)據(jù),插入數(shù)據(jù)時(shí)的緩沖。為Innodb加速優(yōu)化首要參數(shù)。

該參數(shù)分配內(nèi)存的原則:這個(gè)參數(shù)默認(rèn)分配只有8M,可以說是非常小的一個(gè)值。這個(gè)參數(shù)不能動(dòng)態(tài)更改,所以分配需多考慮

。分配過大,會(huì)使Swap占用過多,致使Mysql的查詢特慢。

設(shè)置方法:

例如 innodb_buffer_pool_size=4G

第二個(gè):

innodb_additional_mem_pool:

作用:用來存放Innodb的內(nèi)部目錄

這個(gè)值不用分配太大,系統(tǒng)可以自動(dòng)調(diào)。不用設(shè)置太高。通常比較大數(shù)據(jù)設(shè)置16M夠用了,如果

表比較多,可以適當(dāng)?shù)脑龃蟆H绻@個(gè)值自動(dòng)增加,會(huì)在error log有中顯示的。


mysql 慢查詢配置命令

delimiter ;//改變sql語句執(zhí)行結(jié)束符

SHOW VARIABLES LIKE 'long_query_time';//查看一下默認(rèn)為慢查詢的時(shí)間10秒

SET global ?long_query_time = 1;//設(shè)置成1秒,加上global,下次進(jìn)mysql已然生效?

SELECT * FROM emp WHERE empno = 1234567;//慢查詢語句

SHOW STATUS LIKE 'slow_queries';//查看一下當(dāng)前有多少慢查詢

set global slow_query_log = 'ON';//啟用慢查詢

show variables like '%slow%';//查看一下慢查詢是不是已經(jīng)開啟

innodb和myisam的存儲結(jié)構(gòu):

myism物理文件結(jié)構(gòu)為:

.frm文件:與表相關(guān)的元數(shù)據(jù)信息都存放在frm文件,包括表結(jié)構(gòu)的定義信息等。

.myd文件:myisam存儲引擎專用,用于存儲myisam表的數(shù)據(jù)

.myi文件:myisam存儲引擎專用,用于存儲myisam表的索引相關(guān)信息

innodb的物理文件結(jié)構(gòu)為:

.frm與表相關(guān)的元數(shù)據(jù)信息都存放在frm文件,包括表結(jié)構(gòu)的定義信息等。

.ibd文件和.ibdata文件:

這兩種文件都是存放innodb數(shù)據(jù)的文件,之所以用兩種文件來存放innodb的數(shù)據(jù),是因?yàn)閕nnodb的數(shù)據(jù)存儲方式能夠通過配置來決定是使用共享表空間存放存儲數(shù)據(jù),還是用獨(dú)享表空間存放存儲數(shù)據(jù)。

獨(dú)享表空間存儲方式使用.ibd文件,并且每個(gè)表一個(gè)ibd文件

共享表空間存儲方式使用.ibdata文件,所有表共同使用一個(gè)ibdata文件


表的范式,是首先符合1NF,才能滿足2NF ,進(jìn)一步滿足3NF

1NF:即表的列的具有原子性,不可再分解,即列的信息,不能再分解。

?數(shù)據(jù)庫的分類

關(guān)系型數(shù)據(jù)庫:mysql/oracle/db2/informix/sysbase/sql server

2NF:表中的記錄是唯一的,就滿足2NF,通常我們設(shè)計(jì)一個(gè)主鍵來實(shí)現(xiàn)

3NF:即表中不要有冗余數(shù)據(jù),就是說,表的信息,如果能夠被推導(dǎo)出來,就不應(yīng)該單獨(dú)的設(shè)計(jì)一個(gè)字段來存放.比如下面的設(shè)計(jì)就是不滿足3NF:


反3NF :但是,沒有冗余的數(shù)據(jù)庫未必是最好的數(shù)據(jù)庫,有時(shí)為了提高運(yùn)行效率,就必須降低范式標(biāo)準(zhǔn),適當(dāng)保留冗余數(shù)據(jù)。具體做法是:在概念數(shù)據(jù)模型設(shè)計(jì)時(shí)遵守第三范式,降低范式標(biāo)準(zhǔn)的工作放到物理數(shù)據(jù)模型設(shè)計(jì)時(shí)考慮。降低范式就是增加字段,允許冗余。

Sql語句本身的優(yōu)化

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

①首先我們了解mysql數(shù)據(jù)庫的一些運(yùn)行狀態(tài)如何查詢(比如想知道當(dāng)前mysql運(yùn)行的時(shí)間/一共執(zhí)行了多少次select/update/delete.. /當(dāng)前連接)

show status

常用的:

show status like ‘uptime’ ;

showstauts like ‘com_select’showstauts like ‘com_insert’ ...類推updatedelete

?show [session|global] status like ....如果你不寫[session|global]默認(rèn)是session會(huì)話,指取出當(dāng)前窗口的執(zhí)行,如果你想看所有(從mysql啟動(dòng)到現(xiàn)在,則應(yīng)該global)

show status like ‘connections’;

//顯示慢查詢次數(shù)

show status like ‘slow_queries’;

②如何去定位慢查詢

默認(rèn)情況下,mysql認(rèn)為10秒才是一個(gè)慢查詢.

l修改mysql的慢查詢.

show variables like ‘long_query_time’ ; //可以顯示當(dāng)前慢查詢時(shí)間

set long_query_time=1 ;//可以修改慢查詢時(shí)間

命令執(zhí)行結(jié)束符修改命令:delimiter$$

③set long_query_time=1 ;執(zhí)行后這時(shí)我們?nèi)绻霈F(xiàn)一條語句執(zhí)行時(shí)間超過1秒中,就會(huì)統(tǒng)計(jì)到.

④如果把慢查詢的sql記錄到我們的一個(gè)日志中

在默認(rèn)情況下,我們的mysql不會(huì)記錄慢查詢,需要在啟動(dòng)mysql時(shí)候,指定記錄慢查詢才可以

bin\mysqld.exe - -safe-mode- -slow-query-log [mysql5.5可以在my.ini指定]這個(gè)是windows平臺

先關(guān)閉mysql,再啟動(dòng),如果啟用了慢查詢?nèi)罩荆J(rèn)把這個(gè)文件放在

my.ini文件中記錄的位置

#Path to the database root

datadir="C:/Documents and Settings/AllUsers/Application Data/MySQL/MySQL Server 5.5/Data/"

⑤測試,可以看到在日志中就記錄下我們的mysql慢sql語句.

優(yōu)化問題.

通過explain語句可以分析,mysql如何執(zhí)行你的sql語句。

添加索引

u四種索引(主鍵索引/唯一索引/全文索引/普通索引)

1.添加

1.1主鍵索引添加

當(dāng)一張表,把某個(gè)列設(shè)為主鍵的時(shí)候,則該列就是主鍵索引

create table aaa

(id int unsigned primary key auto_increment,

name varchar(32) not null defaul ‘’);

這是id列就是主鍵索引.

如果你創(chuàng)建表時(shí),沒有指定主鍵索引,也可以在創(chuàng)建表后,在添加,指令:

alter table表名add primary key (列名);

舉例:

create table bbb (id int , name varchar(32)not null default ‘’);

alter table bbb add primary key (id);

1.2普通索引

一般來說,普通索引的創(chuàng)建,是先創(chuàng)建表,然后在創(chuàng)建普通索引

比如:

create table ccc(

id int unsigned,

name varchar(32)

)

alter table test add index tag_count_idx(tag_count);

1.3創(chuàng)建全文索引

全文索引,主要是針對對文件,文本的檢索,比如文章,全文索引針對MyISAM有用.

創(chuàng)建:

CREATE TABLE articles (

id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,

title VARCHAR(200),

body TEXT,

FULLTEXT (title,body)

)engine=myisam charset utf8;

INSERT INTO articles (title,body) VALUES

('MySQL Tutorial','DBMS stands for DataBase ...'),

('How To Use MySQL Well','After you went through a ...'),

('Optimizing MySQL','In this tutorial we will show ...'),

('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),

('MySQL vs. YourSQL','In the following database comparison ...'),

('MySQL Security','When configured properly, MySQL ...');

如何使用全文索引:

錯(cuò)誤用法:

select * from articles where body like ‘%mysql%’;【不會(huì)使用到全文索引】

證明:

explainselect * from articles where body like ‘%mysql%’

正確的用法是:

select * from articles where

match(title,body) against(‘database’);【可以】

?說明:

1.在mysql中fulltext索引只針對myisam生效

2.mysql自己提供的fulltext針對英文生效->sphinx

(coreseek)技術(shù)處理中文

3.使用方法是match(字段名..) against(‘關(guān)鍵字’)

4.全文索引一個(gè)叫停止詞,因?yàn)樵谝粋€(gè)文本中,創(chuàng)建索引是一個(gè)無窮大的數(shù),因此,對一些常用詞和字符,就不會(huì)創(chuàng)建,這些詞,稱為停止詞.

1.4唯一索引

①當(dāng)表的某列被指定為unique約束時(shí),這列就是一個(gè)唯一索引

create table ddd(id int primary keyauto_increment , name varchar(32) unique);

alter table test add unique index user_id_idx (user_id);

這時(shí), name列就是一個(gè)唯一索引.

unique字段可以為NULL,并可以有多NULL,但是如果是具體內(nèi)容,則不能重復(fù).

主鍵字段,不能為NULL,也不能重復(fù).

②在創(chuàng)建表后,再去創(chuàng)建唯一索引

create table eee(id int primary keyauto_increment, name varchar(32));

2.查詢索引

desc表名【該方法的缺點(diǎn)是: 不能夠顯示索引名.】

show index(es) from表名

show keys from表名

3.刪除

alter table表名drop index索引名;

如果刪除主鍵索引。

alter table表名drop primary key[這里有一個(gè)小問題]

4.修改

先刪除,再重新創(chuàng)建.

u為什么創(chuàng)建索引后,速度就會(huì)變快?

原理示意圖:

u索引使用的注意事項(xiàng)


索引的代價(jià):

1.占用磁盤空間

2.對dml操作有影響,變慢

u在哪些列上適合添加索引?

總結(jié):滿足以下條件的字段,才應(yīng)該創(chuàng)建索引.

a:肯定在where條經(jīng)常使用b:該字段的內(nèi)容不是唯一的幾個(gè)值(sex) c:字段內(nèi)容不是頻繁變化.

u使用索引的注意事項(xiàng)

把dept表中,我增加幾個(gè)部門:

alter table dept add index my_ind(dname,loc); //dname左邊的列,loc就是右邊的列

說明,如果我們的表中有復(fù)合索引(索引作用在多列上),此時(shí)我們注意:

1,對于創(chuàng)建的多列索引,只要查詢條件使用了最左邊的列,索引一般就會(huì)被使用。

explain select * from dept where loc='aaa'\G

就不會(huì)使用到索引

2,對于使用like的查詢,查詢?nèi)绻恰?aaa’不會(huì)使用到索引

‘a(chǎn)aa%’會(huì)使用到索引。

比如: explainselect * from dept where dname like '%aaa'\G

不能使用索引,即,在like查詢時(shí),關(guān)鍵的‘關(guān)鍵字’ ,最前面,不能使用%或者_(dá)這樣的字符.,如果一定要前面有變化的值,則考慮使用全文索引->sphinx.

3.如果條件中有or,即使其中有條件帶索引也不會(huì)使用。換言之,就是要求使用的所有字段,都必須建立索引,我們建議大家盡量避免使用or關(guān)鍵字

select * fromdept where dname=’xxx’ or loc=’xx’ or deptno=45

4.如果列類型是字符串,那一定要在條件中將數(shù)據(jù)使用引號引用起來。否則不使用索引。(添加時(shí),字符串必須’’),也就是,如果列是字符串類型,就一定要用‘’把他包括起來.

5.如果mysql估計(jì)使用全表掃描要比使用索引快,則不使用索引。

explain可以幫助我們在不真正執(zhí)行某個(gè)sql語句時(shí),就執(zhí)行mysql怎樣執(zhí)行,這樣利用我們?nèi)シ治鰏ql指令.

u如何查看索引使用的情況:

show status like‘Handler_read%’;

大家可以注意:

handler_read_key:這個(gè)值越高越好,越高表示使用索引查詢到的次數(shù)。

handler_read_rnd_next:這個(gè)值越高,說明查詢低效。

usql語句的小技巧

1.在使用group by分組查詢是,默認(rèn)分組后,還會(huì)排序,可能會(huì)降低速度.

比如:

在group by后面增加order by null就可以防止排序.

2.有些情況下,可以使用連接來替代子查詢。因?yàn)槭褂胘oin,MySQL不需要在內(nèi)存中創(chuàng)建臨時(shí)表。

select * from

dept, emp where dept.deptno=emp.deptno; [簡單處理方式]

select * fromdept left join emp on dept.deptno=emp.deptno;[左外連接,更ok!]

如何選擇mysql的存儲引擎

在開發(fā)中,我們經(jīng)常使用的存儲引擎myisam / innodb/ memory

myisam存儲:如果表對事務(wù)要求不高,同時(shí)是以查詢和添加為主的,我們考慮使用myisam存儲引擎. ,比如bbs中的發(fā)帖表,回復(fù)表.

INNODB存儲:對事務(wù)要求高,保存的數(shù)據(jù)都是重要數(shù)據(jù),我們建議使用INNODB,比如訂單表,賬號表.

問MyISAM和INNODB的區(qū)別

1.MySQL默認(rèn)采用的是MyISAM

2.MyISAM不支持事務(wù),而InnoDB支持

3.InnoDB支持?jǐn)?shù)據(jù)行鎖定,MyISAM不支持行鎖定

4.InnoDB支持外鍵,MyISAM不支持

5 InnoDB的主鍵范圍更大,最大是MyISAM的2倍。

6 InnoDB不支持全文索引,而MyISAM支持

7 MyISAM支持GIS數(shù)據(jù)

8 沒有where的count(*)使用MyISAM要比InnoDB快得多

Memory存儲,比如我們數(shù)據(jù)變化頻繁,不需要入庫,同時(shí)又頻繁的查詢和修改,我們考慮使用memory,速度極快.

如果你的數(shù)據(jù)庫的存儲引擎是myisam,請一定記住要定時(shí)進(jìn)行碎片整理

舉例說明:

create tabletest100(id int unsigned ,name varchar(32))engine=myisam;

insert intotest100 values(1,’aaaaa’);

insert intotest100 values(2,’bbbb’);

insert intotest100 values(3,’ccccc’);

我們應(yīng)該定義對myisam進(jìn)行整理

optimize tabletest100;

mysql_query(“optimize

tables $表名”);

如何在linux下完成定時(shí)任務(wù):

linux如何備份.

1.直接執(zhí)行PHP腳本,需要在同一個(gè)服務(wù)器上執(zhí)行.

# crontab -e

00 * * * * /usr/local/bin/php/home/htdocs/phptimer.php

2.通過HTTP請求來觸發(fā)腳本, PHP文件允許不在同一服務(wù)器上

# crontab -e

00 * * * * /usr/bin/wget -q -O temp.txthttp://www.phptimer.com/phptimer.php

上面是通過wget來請求PHP文件, PHP輸出會(huì)保存在臨時(shí)文件temp.txt中

# crontab -e

00 * * * * /usr/bin/curl -o temp.txt http://www.phptimer.com/phptimer.php

上面是通過curl -o來請求PHP文件, PHP輸出會(huì)保存在臨時(shí)文件temp.txt中

# crontab -e

00 * * * * lynx -dumphttp://www.phptimer.com/phptimer.php

上面是通過Lynx文本瀏覽器來請求PHP文件

n分表技術(shù)

分表技術(shù)有(水平分割和垂直分割)

當(dāng)一張?jiān)絹碓酱髸r(shí)候,即使添加索引還慢的話,我們可以使用分表

以qq用戶表來具體的說明一下分表的操作.

思路如圖:

首先我創(chuàng)建三張表user0

/ user1 /user2 ,然后我再創(chuàng)建uuid表,該表的作用就是提供自增的id,

走代碼:

create table user0(

id int unsigned primary key ,

name varchar(32) not null default '',

pwdvarchar(32) not null default '')

engine=myisam charset utf8;

create table user1(

id int unsigned primary key ,

name varchar(32) not null default '',

pwdvarchar(32) not null default '')

engine=myisam charset utf8;

create table user2(

id int unsigned primary key ,

name varchar(32) not null default '',

pwdvarchar(32) not null default '')

engine=myisam charset utf8;

create table uuid(

id int unsigned primary keyauto_increment)engine=myisam charset utf8;

編寫addUser.php

//注冊一個(gè)用戶

$con=mysql_connect("localhost","root","root");

if(!$con){

die("連接失敗!");

}

mysql_select_db("temp",$con);

$name=$_GET['name'];

$pwd=$_GET['pwd'];

//這時(shí)我們先獲取用戶id,id是從uuid表獲取

$sql="insertinto uuid values(null)";

if(mysql_query($sql,$con)){

$id=mysql_insert_id();

}

//計(jì)算表名,就是,你應(yīng)該把這個(gè)用戶放入到哪個(gè)表

$talname='user'.$id%3;

$sql="insertinto {$talname} values ($id,'$name','$pwd')";

if(mysql_query($sql,$con)){

echo'添加用戶到'.$talname.'ok';

}

mysql_close($con);

//

//注冊一個(gè)用戶

$con=mysql_connect("localhost","root","root");

if(!$con){

die("連接失敗!");

}

mysql_select_db("temp",$con);

$id=intval($_GET['id']);

//計(jì)算表名

$tabname='user'.$id%3;

$sql="selectpwd from {$tabname} where id=$id";

$res=mysql_query($sql,$con);

if($row=mysql_fetch_assoc($res)){

echo"在{$tabname}.中發(fā)現(xiàn)id號為{$id}";

}

//.....

n垂直分割

示意圖:


一句話:如果一張表某個(gè)字段,信息量大,但是我們很少查詢,則可以考慮把這些字段,單獨(dú)的放入到一張表中,這種方式稱為垂直分割.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,786評論 6 534
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,656評論 3 419
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,697評論 0 379
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,098評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,855評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,254評論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,322評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,473評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,014評論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,833評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,016評論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,568評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,273評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,680評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,946評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,730評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,006評論 2 374

推薦閱讀更多精彩內(nèi)容