Mysql性能優(yōu)化二

建立適當?shù)乃饕?br>

說起提高數(shù)據(jù)庫性能,索引是最物美價廉的東西了。不用加內存,不用改程序,不用調sql,只要執(zhí)行個正確的'create index',查詢速度就可能提高百倍千倍,這可真有誘惑力。可是天下沒有免費的午餐,查詢速度的提高是以插入、更新、刪除的速度為代價的,這些寫操作,增加了大量的I/O。

是不是建立一個索引就能解決所有的問題?ename上沒有建立索引會怎樣?

UPDATE emp set ename='zhangsan' where empno=100002;

select * from emp where ename='zhangsan';

我emp表中有2446297條記錄,empno創(chuàng)建索引前,執(zhí)行查詢花了16秒鐘,進行了全表掃描

explain SELECT * from emp where empno=100002;

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

*添加主鍵

ALTER TABLE emp ADD PRIMARY KEY(empno);

再執(zhí)行查詢,執(zhí)行時間顯示0,用explain分析

*刪除主鍵

alter table emp drop primary key;

索引的原理說明

沒有索引為什么會慢?

使用索引為什么會快?

btree類型的索引,就是使用的二分查找法,肯定快啊,算法復雜度是log2N,也就是說16條數(shù)據(jù)查4次,32條數(shù)據(jù)查5次,64條數(shù)據(jù)查6次....依次類推。

使用索引跟沒使用索引的區(qū)別,就跟我們使用新華字典查字,一個是根據(jù)拼音或者筆畫查找,一個是從頭到尾一頁一頁翻。

索引的代價

1、磁盤占用

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

btree 方式檢索,算法復雜度: log2N 次數(shù)

哪些列上適合添加索引

1、較頻繁的作為查詢條件字段應該創(chuàng)建索引

select * from emp where empno = 1;

2、唯一性太差的字段不適合單獨創(chuàng)建索引,即使頻繁作為查詢條件

select * from emp where sex = '男'

3、更新非常頻繁的字段不適合創(chuàng)建索引

select * from emp where logincount = 1

4、不會出現(xiàn)在WHERE子句中的字段不該創(chuàng)建索引

索引的類型

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

唯一索引 (UNIQUE)

普通索引 (INDEX)

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

綜合使用=>復合索引

簡述mysql四種索引的區(qū)別

PRIMARY 索引 =》在主鍵上自動創(chuàng)建

UNIQUE 索引=> 只要是UNiQUE 就是Unique索引.(只能在字段內容不重復的情況下,才能創(chuàng)建唯一索引)

INDEX 索引=>就是普通索引

FULLTEXT => 只在MYISAM 存儲引擎支持, 目的是全文索引,在內容系統(tǒng)中用的多, 在全英文網(wǎng)站用多(英文詞獨立). 中文數(shù)據(jù)不常用,意義不大,國內全文索引通常使用 sphinx來完成,全文索引只能在 char varchar text字段創(chuàng)建.

全文索引案例

1.創(chuàng)建表

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

2.建立全文索引

create fulltext index ful_inx on news (con);

3.插入數(shù)據(jù)

這里要注意,對于常見的英文 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(列名,..); 聯(lián)合主鍵

刪除索引

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;

修改索引,我們一般是先刪除再重新創(chuàng)建.

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

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

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

2,對于使用like的查詢,查詢如果是 '%aaa' 不會使用到索引, 'aaa%' 會使用到索引。

下列的表將不使用索引:

1,如果條件中有or,即使其中有條件帶索引也不會使用。

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

3,like查詢是以%開頭

4,如果列類型是字符串,那一定要在條件中將數(shù)據(jù)使用引號引用起來。否則不使用索引。(添加時,字符串必須'')

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 ;

--放入數(shù)據(jù),前面應該已經(jīng)添加了,如果沒有則需要重新添加

--測試開始.

添加一個主鍵索引

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)

--創(chuàng)建多列索引

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

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

explain select * from dept where dname='研發(fā)部'; 會顯示使用到了索引myind

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

--對于使用like的查詢

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

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

--如果條件中有or,即使其中有條件帶索引也不會使用

--為了演示,我們把復合索引刪除,然后只在dname上加入索引.

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

--如果列類型是字符串,那一定要在條件中將數(shù)據(jù)使用引號引用起來。否則不使用索引

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

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

查看索引的使用情況

show status like 'Handler_read%';

大家可以注意:

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

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

* 這時我們會看到handler_read_rnd_next值很高,為什么,這是因為我們前面沒有加索引的時候,做過多次查詢的原因.

常用SQL優(yōu)化

大批量插入數(shù)據(jù)(MySql管理員) 了解

對于MyISAM:

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

對于Innodb:

1,將要導入的數(shù)據(jù)按照主鍵排序

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

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

優(yōu)化group by 語句

默認情況,MySQL對所有的group by col1,col2進行排序。這與在查詢中指定order by col1, col2類似。如果查詢中包括group by但用戶想要避免排序結果的消耗,則可以使用order by null禁止排序

有些情況下,可以使用連接來替代子查詢。

因為使用join,MySQL不需要在內存中創(chuàng)建臨時表。(講解)

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

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不需要在內存中創(chuàng)建臨時表。

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

和下面比較就可以說明問題!!

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

選擇合適的存儲引擎

MyISAM:Mysql5.5默認的MySQL存儲引擎。如果應用是以讀操作和插入操作為主,只有很少的更新和刪除操作,并且對事務的完整性要求不是很高。其優(yōu)勢是訪問的速度快。

InnoDB:Mysql5.6默認的MySQL存儲引擎,提供了具有提交、回滾和崩潰恢復能力的事務安全。但是對比MyISAM,寫的處理效率差一些并且會占用更多的磁盤空間。

Memory:數(shù)據(jù)存在內存中,服務重啟時,數(shù)據(jù)丟失

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

InnoDB 支持事務和外鍵

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

如果選用小原則:

1.如果追求速度,不在乎數(shù)據(jù)是否一直保存,也不考慮事務,請選擇 memory 比如存放用戶在線狀態(tài).

2.如果表的數(shù)據(jù)要持久保存,應用是以讀操作和插入操作為主,只有很少的更新和刪除操作,并且對事務的完整性要求不是很高。選用MyISAM

3.如果需要數(shù)據(jù)持久保存,并提供了具有提交、回滾和崩潰恢復能力的事務安全,請選用Innodb

選擇合適的數(shù)據(jù)類型

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

對于存儲引擎是MyISAM的數(shù)據(jù)庫,如果經(jīng)常做刪除和修改記錄的操作,要定時執(zhí)行optimize table table_name;功能對表進行碎片整理。

日期類型要根據(jù)實際需要選擇能夠滿足應用的最小存儲的早期類型

create table bbs(id int ,con varchar(1024) , pub_time int);

date('Ymd',時間-3*24*60*60); 2038年-1-19

對于使用浮點數(shù)和定點數(shù)的案例說明

create table temp1( t1 float(10,2), t2 decimal(10,2));

insert into temp1 values(1000000.32,1000000,32); 發(fā)現(xiàn) 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; --發(fā)現(xiàn)該表對應的數(shù)據(jù)文件沒有變小

定期執(zhí)行 optimize table temp2 發(fā)現(xiàn)表大小變化,碎片整理完畢

對于InnoDB它的數(shù)據(jù)會存在data/ibdata1目錄下,在data/數(shù)據(jù)庫/只有一個 *.frm表結構文件.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • mysql數(shù)據(jù)庫中 :database : 文件夾table : 數(shù)據(jù)表(數(shù)據(jù)文件) 進入mysqlmysql -...
    賦閑閱讀 640評論 0 0
  • 筆記: 一、聚合函數(shù):計數(shù) 最大值 最小值 平均數(shù) 求和 1.計數(shù) COUNT() 忽略NULL值 方式1:COU...
    鳳之鳩閱讀 5,678評論 0 1
  • Mysql數(shù)據(jù)庫的優(yōu)化技術 對mysql優(yōu)化時一個綜合性的技術,主要包括 a:表的設計合理化(符合3NF) b:添...
    烈焰焚燒閱讀 496評論 0 2
  • 5.多表查詢 多表查詢 目的:從多張表獲取數(shù)據(jù) 前提:進行連接的多張表中有共同的列 等連接 通過兩個表具有相同意義...
    喬震閱讀 1,548評論 0 0
  • 認真的那個人開玩笑的始就是輸?shù)?,你逼得越緊,他離去的越快。 而且還有很重要的一點就是,千萬不要花費巨大的精力來給自...
    歐幾得里閱讀 142評論 0 2

友情鏈接更多精彩內容