MySQL應用優化

1、基本語句優化原則mysql

(1).儘可能避免在索引列上進行運算或函數操做,這樣會致使索引失效sql

如:數據庫

select * from t where Year(d)>=2016;

能夠優化爲:安全

select * from t where d>='2016-01-01';

(2).使用join語句時,應用小結果集驅動大結果集。由於在join多表時,可能會致使更多的鎖定和擁塞服務器

(3).注意模糊查詢時避免%%,%開頭的查詢條件會使索引失效併發

(4).僅列出須要查詢的字段,這對效率沒有影響,但會影響內存less

如:數據庫設計

select * from t;

能夠優化爲:函數

select name from t;

(5).使用批量交互插入語句以節省交互
如:高併發

insert into t(id,name) values(1,"a");

insert into t(id,name) values(2,"b");

能夠優化爲:

insert into t(id,name) values(1,"a"),(2,"b");

這裏也有博友質疑,貼結果:

(6).limit的基數比較大時使用between

如:

select * from article order by id limit 100000,10;

能夠優化爲:

select * from article between 100000 and 100010 order by id;

這裏須要注意的是,若是id不連續的話,使用between得到的數據量會少於預計的數據量。

(7).避免使用NULL,這樣會使mysql先進行一次是否爲NULL的斷定

(8).(這裏很有爭議,經測試並查閱一下資料修改以下)

若是id做爲非主鍵字段,不要使用count(id),而是count(*),由於id未做非空約束時,會先進行NULL值斷定

id做爲主鍵時,在效率上,count(id)>count(*),若id做爲自增主鍵,count(id)的效率會更高

(9).不要作沒必要要的排序,儘可能在索引中進行排序

 

2、Mysql的存儲引擎分析

  MyISAM Memory InnoDB
用途 快讀 內存數據 完整的事務支持
全表鎖定 全表鎖定 多重隔離級別的行鎖
持久性 基於表恢復 無磁盤I/O,無可持久性 基於日誌的恢復
事務特性 不支持 不支持 支持
支持索引類型 B-tree/FullText/R-tree Hash/B-tree Hash/B-tree

在介紹存儲引擎的選擇原則以前,先介紹一下讀寫比。讀寫比,即讀取和寫入語句執行次數的比,通常理想的讀寫比在100:1左右。

當讀寫比達到10:1的時候,即認爲其是以寫爲主的數據庫。

(1).採用MyISAM引擎(關鍵是快讀,最簡版的MySQL數據庫)

R/W>100:1,且update較少

併發不高,不須要事務

表數據量小,硬件資源差

(2).採用InnoDB引擎(功能完備的MySQL數據庫)

R/W比較小,數據更新頻繁

海量數據,高併發

安全性、可用性高

(3).採用Memory引擎

內存充足

對數據一致性要求不高

按期歸檔(將過期的歷史數據存入文件系統)

 

最經常使用的兩種引擎是MyISAM和InnoDB,MyISAM注重效率,InnoDB注重事務。

 

3、數據庫設計

一、範式與反範式

在數據庫理論發展的過程當中,逐漸造成五大範式,從第一範式到第五範式,數據庫冗餘下降,但查詢效率也會隨之下降。

上世紀硬件設備並不發達,空間成本比較高,因此設計理念是提升範式等級,減小冗餘,利用時間換取空間,平衡點基本落在第三範式上。那什麼又是反範式呢?隨着硬件設備的發展,空間成本大幅度下降,而更多的是對時間和效率的要求,因此範式等級能夠適當下降,增長冗餘,最低可把範式降到第一範式。

反範式示例,因爲一條記錄被分到多張表中進行記錄,查詢須要進行多表關聯,當要查詢的數據量很大時,連表查詢的時間成本就會很高,更嚴重的狀況會引發數據庫服務器宕機。這時候就須要創建冗餘表將數據集中到一個表中記錄。冗餘表通常符合低等級範式。如何減小冗餘表的空間成本呢?通常是按期轉儲。將一段時間以前的數據從數據庫服務器導出,存儲到其餘地方,這些數據應是如今無需使用的數據。

 

2.數據庫分區

講一個數據表的文件和索引分散存儲在不一樣的物理文件中,這樣在查找的時候就不須要在整個大文件中搜索,而在固定範圍中查找。

假設要存儲某一地區1900-2000年之間出生的孩子信息,按年份分區,代碼以下:

create table child (

id int AUTO_INCREMENT,

name varchar(12) not null,

birth date not null,
primary key(id,birth)
) engine=innoDB partition by range (year(birth))

(partition foo01 values less than(1991), partition foo02 values less than(1992),

partition foo03 values less than(1993), partition foo04 values less than(1994),

partition foo05 values less than(1995), partition foo06 values less than(1996),

partition foo07 values less than(1997), partition foo08 values less than(1998),

partition foo09 values less than(1999), partition foo10 values less than(2000));

 

3.數據庫分表

分表原理和分區相似,只不過度區是在不一樣文件中存儲數據,而分表是將一張數據庫表拆分紅多張數據庫表。

如:
 

create table child (

id int primary key AUTO_INCREMENT,

name varchar(12) not null,

birth date not null) engine=innoDB;

可分爲:
 

create table child_xxxx(

id int primary key AUTO_INCREMENT,

name varchar(12) not null,

birth date not null) engine=innoDB;

 

child_xxxx表明出生年份,如child_1900保存1900年出生的孩子信息,child_1901保存1901年出生的孩子信息,以此類推。

 

總之,數據庫應用設計還得根據具體的環境來選擇適當的方案。空間和時間的平衡,根據須要具體狀況來把握。

相關文章
相關標籤/搜索