MySQL優化的幾個大方向
硬件優化
cpu,內存,硬盤等硬件的優化
MySQL參數優化
設置最大連接數
set globle max_connections = 5000;
long_query_time = 2 超過兩秒的查詢記錄下來
log_slow_queries = /data/mysql/slowlog.log
query_cache_size = 64M
SQL語句方面的優化
●修改mysql的慢查詢
show variables like ‘long_query_time’ ; //可以顯示當前慢查詢時間
set long_query_time=1 ;//可以修改慢查詢時間
詳情:https://www.cnblogs.com/luyucheng/p/6265594.html
●使用查詢緩存優化查詢
2:SELECT username FROM user WHERE signup_date >= '2014-06-24‘
上面兩條SQL語句的差別就是 CURDATE() ,MySQL的查詢緩存對這個函數不起作用。所以,像 NOW() 和 RAND() 或是其它的諸如此類的SQL函數都不會開啟查詢緩存,因為這些函數的返回是會不定的易變的。所以,你所需要的就是用一個變量來代替MySQL的函數,從而開啟緩存。
●使用EXPLAIN關鍵字檢測查詢
●當只要一行數據時使用LIMIT 1
●只去自己需要的column,避免使用SELECT *
●添加索引(主鍵索引/唯一索引/全文索引/普通索引)
1.添加
1.1主鍵索引添加
當一張表,把某個列設為主鍵的時候,則該列就是主鍵索引
1 create table aaa 2 (id int unsigned primary key auto_increment , 3 name varchar(32) not null defaul '');
這是id 列就是主鍵索引
如果你創建表時,沒有指定主鍵索引,也可以在創建表后,在添加, 指令:
1 alter table 表名 add primary key (列名);
舉例:
1 create table bbb (id int , name varchar(32) not null default ‘’); 2 alter table bbb add primary key (id);
1.2普通索引
一般來說,普通索引的創建,是先創建表,然后在創建普通索引
比如:
1 create table ccc( 2 id int unsigned, 3 name varchar(32) 4 )
1 create index 索引名 on 表 (列1,列名2);
1.3創建全文索引
全文索引,主要是針對對文件,文本的檢索, 比如文章(5.5版本以后,innodb 支持全文索引)
創建 :
1 CREATE TABLE articles ( 2 3 id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, 4 5 title VARCHAR(200), 6 7 body TEXT, 8 9 FULLTEXT (title,body) 10 11 )engine=myisam charset utf8;
1 INSERT INTO articles (title,body) VALUES 2 3 ('MySQL Tutorial','DBMS stands for DataBase ...'), 4 5 ('How To Use MySQL Well','After you went through a ...'), 6 7 ('Optimizing MySQL','In this tutorial we will show ...'), 8 9 ('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'), 10 11 ('MySQL vs. YourSQL','In the following database comparison ...'), 12 13 ('MySQL Security','When configured properly, MySQL ...');
如何使用全文索引:
錯誤用法:
select * from articles where body like ‘%mysql%’; 【不會使用到全文索引】
證明:
1 explain select * from articles where body like ‘%mysql%’
正確的用法是:
1 select * from articles where match(title,body) against(‘database’);
測速匹配度
1 mysql> select id, match(title,body) against('dbms') from articles;
常用的詞語,匹配度反而很低或者為0(假如常用的單詞都要匹配的話,每條數據基本上都會匹配上,那搜索效率就很慢了) 如:
MySQL 使用一個非常簡單的剖析器來將文本分隔成詞。一個“詞”是由文字、數據、“'” 和 “_” 組成的任何字符序列。任何在 stopword 列表上出現的,或太短的(3 個字符或更少的)的 “word” 將被忽略。
在集和查詢中的每個合適的詞根據其在集與查詢中的重要性衡量。這樣,一個出現在多個文檔中的詞將有較低的權重(可能甚至有一個零權重),因為在這個特定的集中,它有較低的語義值。否則,如果詞是較少的,它將得到一個較高的權重。然后,詞的權重將被結合用於計算記錄行的相似性。
這樣一個技術工作可很好地工作與大的集(實際上,它會小心地與之諧調)。 對於非常小的表,詞分類不足以充份地反應它們的語義值,有時這個模式可能產生奇怪的結果。
mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)
在上面的例子中,搜索詞 MySQL 卻沒有得到任何結果,因為這個詞在超過一半的記錄行中出現。同樣的,它被有效地處理為一個 stopword (即,一個零語義值的詞)。這是最理想的行為 -- 一個自然語言的查詢不應該從一個 1GB 的表中返回每個次行(second row)。
匹配表中一半記錄行的詞很少可能找到相關文檔。實際上,它可能會發現許多不相關的文檔。我們都知道,當我們在互聯網上通過搜索引擎試圖搜索某些東西時,這會經常發生。因為這個原因,在這個特殊的數據集中,這樣的行被設置一個低的語義值。
詳情:http://blog.sina.com.cn/s/blog_63426ff901014l2d.html
全文說明:
- 在mysql中fulltext 索引只針對 myisam生效(5.5版本以后,innodb 支持全文索引)
- mysql自己提供的fulltext針對英文生效->sphinx (coreseek) 技術處理中文
- 使用方法是 match(字段名..) against(‘關鍵字’)
- 全文索引一個 叫 停止詞, 因為在一個文本中,創建索引是一個無窮大的數,因此,對一些常用詞和字符,就不會創建,這些詞,稱為停止詞.
1.4唯一索引
①當表的某列被指定為unique約束時,這列就是一個唯一索引
1 create table ddd(id int primary key auto_increment , name varchar(32) unique);
這時, name 列就是一個唯一索引.
unique字段可以為NULL,並可以有多NULL, 但是如果是具體內容,則不能重復.
主鍵字段,不能為NULL,也不能重復.
②在創建表后,再去創建唯一索引
1 create table eee(id int primary key auto_increment, name varchar(32)); 2 create unique index 索引名 on 表名 (列表..);
2.查詢索引
desc 表名 【該方法的缺點是: 不能夠顯示索引名.】
show index(es) from 表名
show keys from 表名
3.刪除
alter table 表名 drop index 索引名;
如果刪除主鍵索引。
alter table 表名 drop primary key
4.修改
先刪除,再重新創建.
二叉樹算法的索引實現原理:
索引的代價:
- 占用磁盤空間
- 對dml操作有影響,變慢
在哪些列上適合添加索引?
總結: 滿足以下條件的字段,才應該創建索引.
a: 肯定在where條經常使用 b: 該字段的內容不是唯一的幾個值(sex) c: 字段內容不是頻繁變化.
使用索引的注意事項
把dept表中,我增加幾個部門:
1 alter table dept add index my_ind (dname,loc); // dname 左邊的列,loc就是右邊的列
說明,如果我們的表中有復合索引(索引作用在多列上), 此時我們注意:
1, 對於創建的多列索引,只要查詢條件使用了最左邊的列,索引一般就會被使用。 explain select * from dept where loc='aaa'\G 就不會使用到索引
2,對於使用like的查詢,查詢如果是 ‘%aaa’ 不會使用到索引,‘aaa%’ 會使用到索引。
比如: explain select * from dept where dname like '%aaa'\G
不能使用索引,即,在like查詢時,關鍵的 ‘關鍵字’ , 最前面,不能使用 % 或者 _這樣的字符., 如果一定要前面有變化的值,則考慮使用 全文索引->sphinx.
3.如果條件中有or,即使其中有條件帶索引也不會使用(select * from dept where dname=’xxx’ or loc=’xx’ or deptno=45)。換言之,就是要求使用的所有字段,都必須建立索引, 我們建議大家盡量避免使用or 關鍵字
4.如果列類型是字符串,那一定要在條件中將數據使用引號引用起來。否則不使用索引。(添加時,字符串必須’’), 也就是,如果列是字符串類型,就一定要用 ‘’ 把他包括起來.
5.如果mysql估計使用全表掃描要比使用索引快,則不使用索引。
表方面的優化
●永遠為每張表設置一個ID主鍵
●越小的列會越快
●建表符合三范式
●選擇合適的存儲引擎
myisam 存儲: 如果表對事務要求不高,同時是以查詢和添加為主的,我們考慮使用myisam存儲引擎. ,比如 bbs 中的 發帖表,回復表.
INNODB 存儲: 對事務要求高,保存的數據都是重要數據,我們建議使用INNODB,比如訂單表,賬號表.
MyISAM 和 INNODB的區別
1. 事務安全
2. 查詢和添加速度
3. 支持全文索引(5.5版本以后,innodb 支持全文索引)
4. 鎖機制
5. 外鍵 MyISAM 不支持外鍵, INNODB支持外鍵
●mysql讀寫分離
●對表進行水平分割
當一張越來越大時候,即使添加索引還慢的話,我們可以使用分表(即存在不同的表里)
●對表進行垂直分割
如果一張表某個字段,信息量大,但是我們很少查詢,則可以考慮把這些字段,單獨的放入到一張表中,這種方式稱為垂直分割
● 如果你的數據庫的存儲引擎是myisam,請一定記住要定時進行碎片整理
optimize table 表名;