mysql常見知識點總結

mysql常見知識點總結php

 

參考:html

http://www.cnblogs.com/hongfei/archive/2012/10/20/2732516.html前端

https://www.cnblogs.com/xuchenliang/p/6844093.htmlmysql

https://www.cnblogs.com/luxiaoxun/p/4694144.htmllinux

https://blog.csdn.net/phantomes/article/details/39552897程序員

https://blog.csdn.net/wendy432/article/details/52319908web

https://www.cnblogs.com/zhizhao/p/7825469.htmlredis

 

 

MySql的優化步驟

MySql優化的通常步驟:算法

1.經過show status 命令瞭解各類sql的執行效率sql

  SHOW STATUS提供msyql服務器的狀態信息

  通常狀況下,咱們只須要了解以」Com」開頭的指令

  show session status like ‘Com%’:顯示當前的鏈接的統計結果

  show global status like ‘Com%’ :顯示自數據庫上次啓動至今的統計結果

  注:默認是session級別的

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

  另外,還有幾個參數須要注意下:

  show status like ‘Connections’// 試圖鏈接MySQL服務器的次數

  show status like ‘Uptime’//服務器工做的時間(單位秒)

  show status like ‘Slow_queries’//慢查詢的次數 (默認是10秒中就當作是慢查詢,以下圖所示)

  

  a) 如何查詢mysql的慢查詢時間

    Show variables like 'long_query_time';

  b) 修改mysql 慢查詢時間

    set long_query_time=2//若是查詢時間超過2秒就算做是慢查詢

2. 定位執行效率較低的SQL語句(dql出現問題的機率較dml的大)

  問題是:如何在一個項目中,找到慢查詢的select語句?

  答案:mysql支持把慢查詢語句記錄到日誌文件中。程序員須要修改php.ini的配置文件,默認狀況下,慢查詢記錄是不開啓的。

  開啓慢查詢記錄的步驟:

  打開 my.ini ,找到 [mysqld] 在其下面添加

  long_query_time = 2

  log-slow-queries = D:/mysql/logs/slow.log #設置把日誌寫在那裏,能夠爲空,系統會給一個缺省的文件

     例子:咱們數據表中有1千萬條的數據量

  DQL語句:SELECT * FROM order_copy WHERE id=12345;

  

  查詢耗時:19s>2s,因此mysql會將該條select語句記錄到慢查詢日誌中

  SELECT * FROM order_copy WHERE id=12345的執行時間:

  添加索引前:19s

  添加索引後:0.08s

3.經過explain分析低效率的SQL語句的執行狀況

  使用explain分析該dql語句:

EXPLAIN SELECT * FROM order_copy WHERE id=12345
會產生以下信息:
select_type:表示查詢的類型。
table:輸出結果集的表
type:表示表的鏈接類型(system和const爲佳)
possible_keys:表示查詢時,可能使用的索引
key:表示實際使用的索引
key_len:索引字段的長度
rows:掃描的行數
Extra:執行狀況的描述和說明

注意:要儘可能避免讓type的結果爲all,extra的結果爲:using filesort

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

  • 經常使用的優化措施是添加索引。添加索引,咱們不用加內存,不用改程序,不用調sql,只要執行個正確的’create index’,查詢速度就可能提升百倍千倍。可是天下沒有免費的午飯,查詢速度的提升是以插入、更新、刪除的速度爲代價的,這些寫操做,增長了大量的I/O。

例如:給字段id添加索引:

ALTER TABLE order_copy ADD PRIMARY KEY(id)

給1千萬的數據添加primary key 須要耗時: 428秒(7分鐘)

EXPLAIN SELECT * FROM order_copy WHERE id=12345

正是由於給id添加了索引,才使得rows的結果爲1

可是索引並非能夠隨便添加的,如下幾種狀況需牢記在心:

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

    select * from order_copy where id = $id

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

   select * from order_copy where sex=’女’

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

    select * from order_copy where order_state=’未付款’

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

索引的類型:

  • PRIMARY 索引      => 在主鍵上自動建立
  • INDEX 索引          => 就是普通索引
  • UNIQUE 索引        => 至關於INDEX + Unique
  • FULLTEXT            => 只在MYISAM 存儲引擎支持, 目的是全文索引,在內容系統中用的多, 在全英文網站用多(英文詞獨立). 中文數據不經常使用,意義不大 國內全文索引一般 使用 sphinx 來完成.

索引的使用

  • 創建索引 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 from table_name;
    show keys from table_name;
    desc table_Name;

相關資料:

explain的使用:http://www.cnblogs.com/you-yang/archive/2012/01/18/2325841.html

 

mysql優化策略

一個成熟的數據庫架構並非一開始設計就具有高可用、高伸縮等特性的,它是隨着用戶量的增長,基礎架構才逐漸完善。這篇博文主要談MySQL數據庫發展週期中所面臨的問題及優化方案,暫且拋開前端應用不說,大體分爲如下五個階段:

一、數據庫表設計

項目立項後,開發部根據產品部需求開發項目,開發工程師工做其中一部分就是對錶結構設計。對於數據庫來講,這點很重要,若是設計不當,會直接影響訪問速度和用戶體驗。影響的因素不少,好比慢查詢、低效的查詢語句、沒有適當創建索引、數據庫堵塞(死鎖)等。固然,有測試工程師的團隊,會作壓力測試,找bug。對於沒有測試工程師的團隊來講,大多數開發工程師初期不會太多考慮數據庫設計是否合理,而是儘快完成功能實現和交付,等項目有必定訪問量後,隱藏的問題就會暴露,這時再去修改就不是這麼容易的事了。

二、數據庫部署

該運維工程師出場了,項目初期訪問量不會很大,因此單臺部署足以應對在1500左右的QPS(每秒查詢率)。考慮到高可用性,可採用MySQL主從複製+Keepalived作雙擊熱備,常見集羣軟件有Keepalived、Heartbeat。

雙機熱備博文:http://lizhenliang.blog.51cto.com/7876557/1362313

三、數據庫性能優化

若是將MySQL部署到普通的X86服務器上,在不通過任何優化狀況下,MySQL理論值正常能夠處理2000左右QPS,通過優化後,有可能會提高到2500左右QPS,不然,訪問量當達到1500左右併發鏈接時,數據庫處理性能就會變慢,並且硬件資源還很富裕,這時就該考慮軟件問題了。那麼怎樣讓數據庫最大化發揮性能呢?一方面能夠單臺運行多個MySQL實例讓服務器性能發揮到最大化,另外一方面是對數據庫進行優化,每每操做系統和數據庫默認配置都比較保守,會對數據庫發揮有必定限制,可對這些配置進行適當的調整,儘量的處理更多鏈接數。

具體優化有如下三個層面

3.1 數據庫配置優化

MySQL經常使用有兩種存儲引擎,一個是MyISAM,不支持事務處理,讀性能處理快,表級別鎖。另外一個是InnoDB,支持事務處理(ACID),設計目標是爲處理大容量數據發揮最大化性能,行級別鎖。

表鎖:開銷小,鎖定粒度大,發生死鎖機率高,相對併發也低。 
行鎖:開銷大,鎖定粒度小,發生死鎖機率低,相對併發也高。

爲何會出現表鎖和行鎖呢?主要是爲了保證數據的完整性,舉個例子,一個用戶在操做一張表,其餘用戶也想操做這張表,那麼就要等第一個用戶操做完,其餘用戶才能操做,表鎖和行鎖就是這個做用。不然多個用戶同時操做一張表,確定會數據產生衝突或者異常。

根據以上看來,使用InnoDB存儲引擎是最好的選擇,也是MySQL5.5之後版本中默認存儲引擎。每一個存儲引擎相關聯參數比較多,如下列出主要影響數據庫性能的參數。

公共參數默認值:

MyISAM參數默認值:

key_buffer_size = 16M 
索引緩存區大小,通常設置物理內存的30-40%

read_buffer_size = 128K 
讀操做緩衝區大小,推薦設置16M或32M

InnoDB參數默認值:

innodb_buffer_pool_size = 128M 
索引和數據緩衝區大小,通常設置物理內存的60%-70%

innodb_buffer_pool_instances = 1 
緩衝池實例個數,推薦設置4個或8個

innodb_flush_log_at_trx_commit = 1 
關鍵參數,0表明大約每秒寫入到日誌並同步到磁盤,數據庫故障會丟失1秒左右事務數據。1爲每執行一條SQL後寫入到日誌並同步到磁盤,I/O開銷大,執行完SQL要等待日誌讀寫,效率低。2表明只把日誌寫入到系統緩存區,再每秒同步到磁盤,效率很高,若是服務器故障,纔會丟失事務數據。對數據安全性要求不是很高的推薦設置2,性能高,修改後效果明顯。

innodb_file_per_table = OFF 
默認是共享表空間,共享表空間idbdata文件不斷增大,影響必定的I/O性能。推薦開啓獨立表空間模式,每一個表的索引和數據都存在本身獨立的表空間中,能夠實現單表在不一樣數據庫中移動。

innodb_log_buffer_size = 8M 
日誌緩衝區大小,因爲日誌最長每秒鐘刷新一次,因此通常不用超過16M

3.2 系統內核優化

大多數MySQL都部署在Linux系統上,因此操做系統的一些參數也會影響到MySQL性能,如下對linux內核進行適當優化。

在linux系統中,若是進程打開的文件句柄數量超過系統默認值1024,就會提示「too many files open」信息,因此要調整打開文件句柄限制。

3.3 硬件配置

加大物理內存,提升文件系統性能。linux內核會從內存中分配出緩存區(系統緩存和數據緩存)來存放熱數據,經過文件系統延遲寫入機制,等知足條件時(如緩存區大小到達必定百分比或者執行sync命令)纔會同步到磁盤。也就是說物理內存越大,分配緩存區越大,緩存數據越多。固然,服務器故障會丟失必定的緩存數據。

SSD硬盤代替SAS硬盤,將RAID級別調整爲RAID1+0,相對於RAID1和RAID5有更好的讀寫性能(IOPS),畢竟數據庫的壓力主要來自磁盤I/O方面。

四、數據庫架構擴展

隨着業務量愈來愈大,單臺數據庫服務器性能已沒法知足業務需求,該考慮加機器了,該作集羣了~~~。主要思想是分解單臺數據庫負載,突破磁盤I/O性能,熱數據存放緩存中,下降磁盤I/O訪問頻率。

4.1 主從複製與讀寫分離

由於生產環境中,數據庫大多都是讀操做,因此部署一主多從架構,主數據庫負責寫操做,並作雙擊熱備,多臺從數據庫作負載均衡,負責讀操做,主流的負載均衡器有LVS、HAProxy、Nginx。怎麼來實現讀寫分離呢?大多數企業是在代碼層面實現讀寫分離,效率比較高。另外一個種方式經過代理程序實現讀寫分離,企業中應用較少,常見代理程序有MySQL Proxy、Amoeba。在這樣數據庫集羣架構中,大大增長數據庫高併發能力,解決單臺性能瓶頸問題。若是從數據庫一臺從庫能處理2000 QPS,那麼5臺就能處理1w QPS,數據庫橫向擴展性也很容易。

有時,面對大量寫操做的應用時,單臺寫性能達不到業務需求。若是作雙主,就會遇到數據庫數據不一致現象,產生這個緣由是在應用程序不一樣的用戶會有可能操做兩臺數據庫,同時的更新操做形成兩臺數據庫數據庫數據發生衝突或者不一致。在單庫時MySQL利用存儲引擎機制表鎖和行鎖來保證數據完整性,怎樣在多臺主庫時解決這個問題呢?有一套基於perl語言開發的主從複製管理工具,叫MySQL-MMM(Master-Master replication managerfor Mysql,Mysql主主複製管理器),這個工具最大的優勢是在同一時間只提供一臺數據庫寫操做,有效保證數據一致性。

主從複製博文:http://lizhenliang.blog.51cto.com/7876557/1290431 
讀寫分離博文:http://lizhenliang.blog.51cto.com/7876557/1305083 
MySQL-MMM博文:http://lizhenliang.blog.51cto.com/7876557/1354576

4.2 增長緩存

給數據庫增長緩存系統,把熱數據緩存到內存中,若是內存緩存中有要請求的數據就再也不去數據庫中返回結果,提升讀性能。緩存實現有本地緩存和分佈式緩存,本地緩存是將數據緩存到本地服務器內存中或者文件中,速度快。分佈式能夠緩存海量數據,擴展容易,主流的分佈式緩存系統有memcached、Redis,memcached性能穩定,數據緩存在內存中,速度很快,QPS可達8w左右。若是想數據持久化那就用redis,性能不低於memcached。

工做過程:

4.3 分庫

分庫是根據業務不一樣把相關的表切分到不一樣的數據庫中,好比web、bbs、blog等庫。若是業務量很大,還可將切分後的庫作主從架構,進一步避免單個庫壓力過大。

4.4 分表

數據量的日劇增長,數據庫中某個表有幾百萬條數據,致使查詢和插入耗時太長,怎麼能解決單表壓力呢?你就該考慮是否把這個表拆分紅多個小表,來減輕單個表的壓力,提升處理效率,此方式稱爲分表。

分表技術比較麻煩,要修改程序代碼裏的SQL語句,還要手動去建立其餘表,也能夠用merge存儲引擎實現分表,相對簡單許多。分表後,程序是對一個總表進行操做,這個總表不存放數據,只有一些分表的關係,以及更新數據的方式,總表會根據不一樣的查詢,將壓力分到不一樣的小表上,所以提升併發能力和磁盤I/O性能。

分表分爲垂直拆分和水平拆分:

垂直拆分:把原來的一個不少字段的表拆分多個表,解決表的寬度問題。你能夠把不經常使用的字段單獨放到一個表中,也能夠把大字段獨立放一個表中,或者把關聯密切的字段放一個表中。

水平拆分:把原來一個表拆分紅多個表,每一個表的結構都同樣,解決單表數據量大的問題。

4.5 分區

分區就是把一張表的數據分紅多個區塊,這些區塊能夠在一個磁盤上,也能夠在不一樣的磁盤上,分區後,表面上仍是一張表,但數據散列在多個位置,這樣一來,多塊硬盤同時處理不一樣的請求,從而提升磁盤I/O讀寫性能,實現比較簡單。

注:增長緩存、分庫、分表和分區主要由程序猿來實現。

五、數據庫維護

數據庫維護是運維工程師或者DBA主要工做,包括性能監控、性能分析、性能調優、數據庫備份和恢復等。

5.1 性能狀態關鍵指標

QPS,Queries Per Second:每秒查詢數,一臺數據庫每秒可以處理的查詢次數

TPS,Transactions Per Second:每秒處理事務數

經過show status查看運行狀態,會有300多條狀態信息記錄,其中有幾個值幫能夠咱們計算出QPS和TPS,以下:

Uptime:服務器已經運行的實際,單位秒 
Questions:已經發送給數據庫查詢數 
Com_select:查詢次數,實際操做數據庫的 
Com_insert:插入次數 
Com_delete:刪除次數 
Com_update:更新次數 
Com_commit:事務次數 
Com_rollback:回滾次數

那麼,計算方法來了,基於Questions計算出QPS:

mysql> show global status like 'Questions'; 
mysql> show global status like 'Uptime';

QPS = Questions / Uptime 
基於Com_commit和Com_rollback計算出TPS:

mysql> show global status like 'Com_commit'; 
mysql> show global status like 'Com_rollback'; 
mysql> show global status like 'Uptime'; 
TPS = (Com_commit + Com_rollback) / Uptime

另外一計算方式:基於Com_select、Com_insert、Com_delete、Com_update計算出QPS

mysql> show global status where Variable_name in('com_select','com_insert','com_delete','com_update');

等待1秒再執行,獲取間隔差值,第二次每一個變量值減去第一次對應的變量值,就是QPSSTPS計算方法:

mysql> show global status where Variable_name in('com_insert','com_delete','com_update');

計算TPS,就不算查詢操做了,計算出插入、刪除、更新四個值便可。

經網友對這兩個計算方式的測試得出,當數據庫中myisam表比較多時,使用Questions計算比較準確。當數據庫中innodb表比較多時,則以Com_*計算比較準確。

5.2 開啓慢查詢日誌

MySQL開啓慢查詢日誌,分析出哪條SQL語句比較慢,使用set設置變量,重啓服務失效,能夠在my.cnf添加參數永久生效。

分析慢查詢日誌,能夠使用MySQL自帶的mysqldumpslow工具,分析的日誌較爲簡單。

mysqldumpslow -t 3 /var/log/mysql/mysql-slow.log #查看最慢的前三個查詢

也能夠使用percona公司的pt-query-digest工具,日誌分析功能全面,可分析slow log、binlog、general log。

分析慢查詢日誌:pt-query-digest /var/log/mysql/mysql-slow.log

分析binlog日誌:mysqlbinlog mysql-bin.000001 >mysql-bin.000001.sql

pt-query-digest –type=binlog mysql-bin.000001.sql

分析普通日誌:pt-query-digest –type=genlog localhost.log

5.3 數據庫備份

備份數據庫是最基本的工做,也是最重要的,不然後果很嚴重,你懂得!但因爲數據庫比較大,上百G,每每備份都很耗費時間,因此就該選擇一個效率高的備份策略,對於數據量大的數據庫,通常都採用增量備份。經常使用的備份工具備mysqldump、mysqlhotcopy、xtrabackup等,mysqldump比較適用於小的數據庫,由於是邏輯備份,因此備份和恢復耗時都比較長。mysqlhotcopy和xtrabackup是物理備份,備份和恢復速度快,不影響數據庫服務狀況下進行熱拷貝,建議使用xtrabackup,支持增量備份。

Xtrabackup備份工具使用博文:http://lizhenliang.blog.51cto.com/7876557/1612800

5.4 數據庫修復

有時候MySQL服務器忽然斷電、異常關閉,會致使表損壞,沒法讀取表數據。這時就能夠用到MySQL自帶的兩個工具進行修復,myisamchk和mysqlcheck。

myisamchk:只能修復myisam表,須要中止數據庫

經常使用參數:

-f –force 強制修復,覆蓋老的臨時文件,通常不使用 
-r –recover 恢復模式 
-q –quik 快速恢復 
-a –analyze 分析表 
-o –safe-recover 老的恢復模式,若是-r沒法修復,能夠使用此參數試試 
-F –fast 只檢查沒有正常關閉的表

快速修復weibo數據庫: 
cd /var/lib/mysql/weibo 
myisamchk -r -q *.MYI

mysqlcheck:myisam和innodb表均可以用,不須要中止數據庫,如修復單個表,可在數據庫後面添加表名,以空格分割

經常使用參數:

-a –all-databases 檢查全部的庫 
-r –repair 修復表 
-c –check 檢查表,默認選項 
-a –analyze 分析表 
-o –optimize 優化表 
-q –quik 最快檢查或修復表 
-F –fast 只檢查沒有正常關閉的表 
快速修復weibo數據庫: 
mysqlcheck -r -q -uroot -p123 weibo

5.5 另外,查看CPU和I/O性能方法

查看CPU性能 
參數-P是顯示CPU數,ALL爲全部,也能夠只顯示第幾顆 
查看I/O性能 
參數-m是以M單位顯示,默認K 
%util:當達到100%時,說明I/O很忙。 
await:請求在隊列中等待時間,直接影響read時間。 
I/O極限:IOPS(r/s+w/s),通常在1200左右。(IOPS,每秒進行讀寫(I/O)操做次數) 
I/O帶寬:在順序讀寫模式下SAS硬盤理論值在300M/s左右,SSD硬盤理論值在600M/s左右。

以上是本人使用MySQL三年來總結的一些主要優化方案,能力有限,有些不太全面,但這些基本可以知足中小型企業數據庫需求。因爲關係型數據庫初衷設計限制,一些BAT公司海量數據放到關係型數據庫中,在海量數據查詢和分析方面已經達不到更好的性能。所以NoSQL火起來了,非關係型數據庫,大數據量,具備高性能,同時也彌補了關係型數據庫某方面不足,漸漸大多數公司已經將部分業務數據庫存放到NoSQL中,如MongoDBHbase等。數據存儲方面採用分佈式文件系統,如HDFS、GFS等。海量數據計算分析採用HadoopSpark、Storm等。這些都是與運維相關的前沿技術,也是在存儲方面主要學習對象,小夥伴們共同加油吧!哪位博友有更好的優化方案,歡迎交流哦。

 

MySQL性能優化總結

1、MySQL的主要適用場景

一、Web網站系統

二、日誌記錄系統

三、數據倉庫系統

四、嵌入式系統

2、MySQL架構圖:

 

3、MySQL存儲引擎概述

1MyISAM存儲引擎

MyISAM存儲引擎的表在數據庫中,每個表都被存放爲三個以表名命名的物理文件。首先確定會有任何存儲引擎都不可缺乏的存放表結構定義信息的.frm文件,另外還有.MYD和.MYI文件,分別存放了表的數據(.MYD)和索引數據(.MYI)。每一個表都有且僅有這樣三個文件作爲MyISAM存儲類型的表的存儲,也就是說無論這個表有多少個索引,都是存放在同一個.MYI文件中。

MyISAM支持如下三種類型的索引:

一、B-Tree索引

B-Tree索引,顧名思義,就是全部的索引節點都按照balancetree的數據結構來存儲,全部的索引數據節點都在葉節點。

二、R-Tree索引

R-Tree索引的存儲方式和b-tree索引有一些區別,主要設計用於爲存儲空間和多維數據的字段作索引,因此目前的MySQL版原本說,也僅支持geometry類型的字段做索引。

三、Full-text索引

Full-text索引就是咱們長說的全文索引,他的存儲結構也是b-tree。主要是爲了解決在咱們須要用like查詢的低效問題。

2Innodb 存儲引擎

一、支持事務安裝

二、數據多版本讀取

三、鎖定機制的改進

四、實現外鍵

3NDBCluster存儲引擎

NDB存儲引擎也叫NDBCluster存儲引擎,主要用於MySQLCluster分佈式集羣環境,Cluster是MySQL從5.0版本纔開始提供的新功能。

4Merge存儲引擎

MERGE存儲引擎,在MySQL用戶手冊中也提到了,也被你們認識爲MRG_MyISAM引擎。Why?由於MERGE存儲引擎能夠簡單的理解爲其功能就是實現了對結構相同的MyISAM表,經過一些特殊的包裝對外提供一個單一的訪問入口,以達到減少應用的複雜度的目的。要建立MERGE表,不只僅基表的結構要徹底一致,包括字段的順序,基表的索引也必須徹底一致。

5Memory存儲引擎

Memory存儲引擎,經過名字就很容易讓人知道,他是一個將數據存儲在內存中的存儲引擎。Memory存儲引擎不會將任何數據存放到磁盤上,僅僅存放了一個表結構相關信息的.frm文件在磁盤上面。因此一旦MySQLCrash或者主機Crash以後,Memory的表就只剩下一個結構了。Memory表支持索引,而且同時支持Hash和B-Tree兩種格式的索引。因爲是存放在內存中,因此Memory都是按照定長的空間來存儲數據的,並且不支持BLOB和TEXT類型的字段。Memory存儲引擎實現頁級鎖定。

6BDB存儲引擎

BDB存儲引擎全稱爲BerkeleyDB存儲引擎,和Innodb同樣,也不是MySQL本身開發實現的一個存儲引擎,而是由SleepycatSoftware所提供,固然,也是開源存儲引擎,一樣支持事務安全。

7FEDERATED存儲引擎

FEDERATED存儲引擎所實現的功能,和Oracle的DBLINK基本類似,主要用來提供對遠程MySQL服務器上面的數據的訪問接口。若是咱們使用源碼編譯來安裝MySQL,那麼必須手工指定啓用FEDERATED存儲引擎才行,由於MySQL默認是不起用該存儲引擎的。

8ARCHIVE存儲引擎

ARCHIVE存儲引擎主要用於經過較小的存儲空間來存放過時的不多訪問的歷史數據。ARCHIVE表不支持索引,經過一個.frm的結構定義文件,一個.ARZ的數據壓縮文件還有一個.ARM的meta信息文件。因爲其所存放的數據的特殊性,ARCHIVE表不支持刪除,修改操

做,僅支持插入和查詢操做。鎖定機制爲行級鎖定。

9BLACKHOLE存儲引擎

BLACKHOLE存儲引擎是一個很是有意思的存儲引擎,功能恰如其名,就是一個「黑洞」。就像咱們unix系統下面的「/dev/null」設備同樣,無論咱們寫入任何信息,都是有去無回。

10CSV存儲引擎

CSV存儲引擎實際上操做的就是一個標準的CSV文件,他不支持索引。起主要用途就是你們有些時候可能會須要經過數據庫中的數據導出成一份報表文件,而CSV文件是不少軟件都支持的一種較爲標準的格式,因此咱們能夠經過先在數據庫中創建一張CVS表,而後將生成的報表信息插入到該表,便可獲得一份CSV報表文件了。

4、影響MySQLServer性能的相關因素

1商業需求對性能的影響

典型需求:一個論壇帖子總量的統計,要求:實時更新。

2系統架構及實現對性能的影響

如下幾類數據都是不適合在數據庫中存放的:

二進制多媒體數據

流水隊列數據

超大文本數據

經過Cache技術來提升系統性能:

系統各類配置及規則數據;

活躍用戶的基本信息數據;

活躍用戶的個性化定製信息數據;

準實時的統計信息數據;

其餘一些訪問頻繁但變動較少的數據;

3 Query語句對系統性能的影響

需求:取出某個group(假設id爲1)下的用戶編號(id),用戶暱稱(nick_name),並按照加入組的時間(user_group.gmt_create)來進行倒序排列,取出前20個。

解決方案一:

SELECT id,nick_name FROM user,user_group WHERE user_group.group_id=1 and user_group.user_id=user.id ORDER BY user_group.gmt_create desc limit 100,20;

解決方案二:

複製代碼
SELECT user.id,user.nick_name FROM(
SELECT user_id
FROM user_group
WHERE user_group.group_id=1
ORDER BY gmt_create desc
limit 100,20)t,user
WHERE t.user_id=user.id;
複製代碼

經過比較兩個解決方案的執行計劃,咱們能夠看到第一中解決方案中須要和user表參與Join的記錄數MySQL經過統計數據估算出來是31156,也就是經過user_group表返回的全部知足group_id=1的記錄數(系統中的實際數據是20000)。而第二種解決方案的執行計劃中,user表參與Join的數據就只有20條,二者相差很大,咱們認爲第二中解決方案應該明顯優於第一種解決方案。

4 Schema設計對系統的性能影響

儘可能減小對數據庫訪問的請求。

儘可能減小無用數據的查詢請求。

5硬件環境對系統性能的影響

一、典型OLTP應用系統

對於各類數據庫系統環境中你們最多見的OLTP系統,其特色是併發量大,總體數據量比較多,但每次訪問的數據比較少,且訪問的數據比較離散,活躍數據佔整體數據的比例不是太大。對於這類系統的數據庫其實是最難維護,最難以優化的,對主機總體性能要求也是最高的。由於不只訪問量很高,數據量也不小。

針對上面的這些特色和分析,咱們能夠對OLTP的得出一個大體的方向。

雖然系統整體數據量較大,可是系統活躍數據在數據總量中所佔的比例不大,那麼咱們能夠經過擴大內存容量來儘量多的將活躍數據cache到內存中;

雖然IO訪問很是頻繁,可是每次訪問的數據量較少且很離散,那麼咱們對磁盤存儲的要求是IOPS表現要很好,吞吐量是次要因素;

併發量很高,CPU每秒所要處理的請求天然也就不少,因此CPU處理能力須要比較強勁;

雖然與客戶端的每次交互的數據量並非特別大,可是網絡交互很是頻繁,因此主機與客戶端交互的網絡設備對流量能力也要求不能太弱。

二、典型OLAP應用系統

用於數據分析的OLAP系統的主要特色就是數據量很是大,併發訪問很少,但每次訪問所須要檢索的數據量都比較多,並且數據訪問相對較爲集中,沒有太明顯的活躍數據概念。

基於OLAP系統的各類特色和相應的分析,針對OLAP系統硬件優化的大體策略以下:

數據量很是大,因此磁盤存儲系統的單位容量須要儘可能大一些;

單次訪問數據量較大,並且訪問數據比較集中,那麼對IO系統的性能要求是須要有儘量大的每秒IO吞吐量,因此應該選用每秒吞吐量儘量大的磁盤;

雖然IO性能要求也比較高,可是併發請求較少,因此CPU處理能力較難成爲性能瓶頸,因此CPU處理能力沒有太苛刻的要求;

雖然每次請求的訪問量很大,可是執行過程當中的數據大都不會返回給客戶端,最終返回給客戶端的數據量都較小,因此和客戶端交互的網絡設備要求並非過高;

此外,因爲OLAP系統因爲其每次運算過程較長,能夠很好的並行化,因此通常的OLAP系統都是由多臺主機構成的一個集羣,而集羣中主機與主機之間的數據交互量通常來講都是很是大的,因此在集羣中主機之間的網絡設備要求很高。

三、除了以上兩個典型應用以外,還有一類比較特殊的應用系統,他們的數據量不是特別大,可是訪問請求及其頻繁,並且大部分是讀請求。可能每秒須要提供上萬甚至幾萬次請求,每次請求都很是簡單,可能大部分都只有一條或者幾條比較小的記錄返回,就好比基於數據庫的DNS服務就是這樣類型的服務。

雖然數據量小,可是訪問極其頻繁,因此能夠經過較大的內存來cache住大部分的數據,這可以保證很是高的命中率,磁盤IO量比較小,因此磁盤也不須要特別高性能的;

併發請求很是頻繁,比須要較強的CPU處理能力才能處理;

雖然應用與數據庫交互量很是大,可是每次交互數據較少,整體流量雖然也會較大,可是通常來講普通的千兆網卡已經足夠了。

5、MySQL 鎖定機制簡介

行級鎖定(row-level)

表級鎖定(table-level)

頁級鎖定(page-level)

在MySQL數據庫中,使用表級鎖定的主要是MyISAM,Memory,CSV等一些非事務性存儲引擎,而使用行級鎖定的主要是Innodb存儲引擎和NDBCluster存儲引擎,頁級鎖定主要是BerkeleyDB存儲引擎的鎖定方式。

6、MySQL Query的優化

Query語句的優化思路和原則主要提如今如下幾個方面:

1. 優化更須要優化的Query;

2. 定位優化對象的性能瓶頸;

3. 明確的優化目標;

4. 從Explain入手;

5. 多使用profile

6. 永遠用小結果集驅動大的結果集;

7. 儘量在索引中完成排序;

8. 只取出本身須要的Columns;

9. 僅僅使用最有效的過濾條件;

10.儘量避免複雜的Join和子查詢;

合理設計並利用索引

1)B-Tree索引

通常來講,MySQL中的B-Tree索引的物理文件大多都是以BalanceTree的結構來存儲的,也就是全部實際須要的數據都存放於Tree的LeafNode,並且到任何一個LeafNode的最短路徑的長度都是徹底相同的,因此咱們你們都稱之爲B-Tree索引固然,可能各類數據庫(或MySQL的各類存儲引擎)在存放本身的B-Tree索引的時候會對存儲結構稍做改造。如Innodb存儲引擎的B-Tree索引實際使用的存儲結構其實是B+Tree,也就是在B-Tree數據結構的基礎上作了很小的改造,在每個LeafNode上面出了存放索引鍵的相關信息以外,還存儲了指向與該LeafNode相鄰的後一個LeafNode的指針信息,這主要是爲了加快檢索多個相鄰LeafNode的效率考慮。

2)Hash索引

Hash索引在MySQL中使用的並非不少,目前主要是Memory存儲引擎使用,並且在Memory存儲引擎中將Hash索引做爲默認的索引類型。所謂Hash索引,實際上就是經過必定的Hash算法,將須要索引的鍵值進行Hash運算,而後將獲得的Hash值存入一個Hash表中。而後每次須要檢索的時候,都會將檢索條件進行相同算法的Hash運算,而後再和Hash表中的Hash值進行比較並得出相應的信息。

Hash索引僅僅只能知足「=」,「IN」和「<=>」查詢,不能使用範圍查詢;

Hash索引沒法被利用來避免數據的排序操做;

Hash索引不能利用部分索引鍵查詢;

Hash索引在任什麼時候候都不能避免表掃面;

Hash索引遇到大量Hash值相等的狀況後性能並不必定就會比B-Tree索引高;

3)Full-text索引

Full-text索引也就是咱們常說的全文索引,目前在MySQL中僅有MyISAM存儲引擎支持,並且也並非全部的數據類型都支持全文索引。目前來講,僅有CHAR,VARCHAR和TEXT這三種數據類型的列能夠建Full-text索引。

索引可以極大的提升數據檢索效率,也可以改善排序分組操做的性能,可是咱們不能忽略的一個問題就是索引是徹底獨立於基礎數據以外的一部分數據,更新數據會帶來的IO量和調整索引所致的計算量的資源消耗。

是否須要建立索引,幾點原則:較頻繁的做爲查詢條件的字段應該建立索引;惟一性太差的字段不適合單首創建索引,即便頻繁做爲查詢條件;更新很是頻繁的字段不適合建立索引;

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

Join語句的優化

儘量減小Join語句中的NestedLoop的循環總次數;「永遠用小結果集驅動大的結果集」。

優先優化NestedLoop的內層循環;

保證Join語句中被驅動表上Join條件字段已經被索引;

當沒法保證被驅動表的Join條件字段被索引且內存資源充足的前提下,不要太吝惜JoinBuffer的設置;

ORDER BYGROUP BYDISTINCT優化

1)ORDER BY的實現與優化

優化Query語句中的ORDER BY的時候,儘量利用已有的索引來避免實際的排序計算,能夠很大幅度的提高ORDER BY操做的性能。

優化排序:

1.加大max_length_for_sort_data參數的設置;

2.去掉沒必要要的返回字段;

3.增大sort_buffer_size參數設置;

2)GROUP BY的實現與優化

因爲GROUP BY實際上也一樣須要進行排序操做,並且與ORDER BY相比,GROUP BY主要只是多了排序以後的分組操做。固然,若是在分組的時候還使用了其餘的一些聚合函數,那麼還須要一些聚合函數的計算。因此,在GROUP BY的實現過程當中,與ORDER BY同樣也能夠利用到索引。

3)DISTINCT的實現與優化

DISTINCT實際上和GROUP BY的操做很是類似,只不過是在GROUP BY以後的每組中只取出一條記錄而已。因此,DISTINCT的實現和GROUP BY的實現也基本差很少,沒有太大的區別。一樣能夠經過鬆散索引掃描或者是緊湊索引掃描來實現,固然,在沒法僅僅使用索引即能完成DISTINCT的時候,MySQL只能經過臨時表來完成。可是,和GROUP BY有一點差異的是,DISTINCT並不須要進行排序。也就是說,在僅僅只是DISTINCT操做的Query若是沒法僅僅利用索引完成操做的時候,MySQL會利用臨時表來作一次數據的「緩存」,可是不會對臨時表中的數據進行filesort操做。

7、MySQL數據庫Schema設計的性能優化

高效的模型設計

適度冗餘-讓Query盡兩減小Join

大字段垂直分拆-summary表優化

大表水平分拆-基於類型的分拆優化

統計表-準實時優化

合適的數據類型

時間存儲格式總類並非太多,咱們經常使用的主要就是DATETIME,DATE和TIMESTAMP這三種了。從存儲空間來看TIMESTAMP最少,四個字節,而其餘兩種數據類型都是八個字節,多了一倍。而TIMESTAMP的缺點在於他只能存儲從1970年以後的時間,而另外兩種時間類型能夠存放最先從1001年開始的時間。若是有須要存放早於1970年以前的時間的需求,咱們必須放棄TIMESTAMP類型,可是隻要咱們不須要使用1970年以前的時間,最好儘可能使用TIMESTAMP來減小存儲空間的佔用。

字符存儲類型

CHAR[(M)]類型屬於靜態長度類型,存放長度徹底以字符數來計算,因此最終的存儲長度是基於字符集的,如latin1則最大存儲長度爲255字節,可是若是使用gbk則最大存儲長度爲510字節。CHAR類型的存儲特色是無論咱們實際存放多長數據,在數據庫中都會存放M個字符,不夠的經過空格補上,M默認爲1。雖然CHAR會經過空格補齊存放的空間,可是在訪問數據的時候,MySQL會忽略最後的全部空格,因此若是咱們的實際數據中若是在最後確實須要空格,則不能使用CHAR類型來存放。

VARCHAR[(M)]屬於動態存儲長度類型,僅存佔用實際存儲數據的長度。TINYTEXT,TEXT,MEDIUMTEXT和LONGTEXT這四種類型同屬於一種存儲方式,都是動態存儲長度類型,不一樣的僅僅是最大長度的限制。

事務優化

1. 髒讀:髒讀就是指當一個事務正在訪問數據,而且對數據進行了修改,而這種修改尚未提交到數據庫中,這時,另一個事務也訪問這個數據,而後使用了這個數據。

2. 不可重複讀:是指在一個事務內,屢次讀同一數據。在這個事務尚未結束時,另一個事務也訪問該同一數據。那麼,在第一個事務中的兩次讀數據之間,因爲第二個事務的修改,那麼第一個事務兩次讀到的的數據多是不同的。這樣就發生了在一個事務內兩次讀到的數據是不同的,所以稱爲是不可重複讀。

3. 幻讀:是指當事務不是獨立執行時發生的一種現象,例如第一個事務對一個表中的數據進行了修改,這種修改涉及到表中的所有數據行。同時,第二個事務也修改這個表中的數據,這種修改是向表中插入一行新數據。那麼,之後就會發生操做第一個事務的用戶發現表中還有沒有修改的數據行,就好象發生了幻覺同樣。

Innodb在事務隔離級別方面支持的信息以下:

1.READ UNCOMMITTED

常被成爲Dirty Reads(髒讀),能夠說是事務上的最低隔離級別:在普通的非鎖定模式下SELECT的執行使咱們看到的數據可能並非查詢發起時間點的數據,於是在這個隔離度下是非Consistent Reads(一致性讀);

2.READ COMMITTED

這一隔離級別下,不會出現DirtyRead,可是可能出現Non-RepeatableReads(不可重複讀)和PhantomReads(幻讀)。

3. REPEATABLE READ

REPEATABLE READ隔離級別是InnoDB默認的事務隔離級。在REPEATABLE READ隔離級別下,不會出現DirtyReads,也不會出現Non-Repeatable Read,可是仍然存在PhantomReads的可能性。

4.SERIALIZABLE

SERIALIZABLE隔離級別是標準事務隔離級別中的最高級別。設置爲SERIALIZABLE隔離級別以後,在事務中的任什麼時候候所看到的數據都是事務啓動時刻的狀態,不論在這期間有沒有其餘事務已經修改了某些數據並提交。因此,SERIALIZABLE事務隔離級別下,PhantomReads也不會出現。

8、可擴展性設計之數據切分

數據的垂直切分

數據的垂直切分,也能夠稱之爲縱向切分。將數據庫想象成爲由不少個一大塊一大塊的「數據塊」(表)組成,咱們垂直的將這些「數據塊」切開,而後將他們分散到多臺數據庫主機上面。這樣的切分方法就是一個垂直(縱向)的數據切分。

垂直切分的優勢

◆數據庫的拆分簡單明瞭,拆分規則明確;

◆應用程序模塊清晰明確,整合容易;

◆數據維護方便易行,容易定位;

垂直切分的缺點

◆部分表關聯沒法在數據庫級別完成,須要在程序中完成;

◆對於訪問極其頻繁且數據量超大的表仍然存在性能平靜,不必定能知足要求;

◆事務處理相對更爲複雜;

◆切分達到必定程度以後,擴展性會遇到限制;

◆過讀切分可能會帶來系統過渡複雜而難以維護。

數據的水平切分

數據的垂直切分基本上能夠簡單的理解爲按照表按照模塊來切分數據,而水平切分就再也不是按照表或者是功能模塊來切分了。通常來講,簡單的水平切分主要是將某個訪問極其平凡的表再按照某個字段的某種規則來分散到多個表之中,每一個表中包含一部分數據。

水平切分的優勢

◆表關聯基本可以在數據庫端所有完成;

◆不會存在某些超大型數據量和高負載的表遇到瓶頸的問題;

◆應用程序端總體架構改動相對較少;

◆事務處理相對簡單;

◆只要切分規則可以定義好,基本上較難遇到擴展性限制;

水平切分的缺點

◆切分規則相對更爲複雜,很難抽象出一個可以知足整個數據庫的切分規則;

◆後期數據的維護難度有所增長,人爲手工定位數據更困難;

◆應用系統各模塊耦合度較高,可能會對後面數據的遷移拆分形成必定的困難。

數據切分與整合中可能存在的問題

1.引入分佈式事務的問題

徹底能夠將一個跨多個數據庫的分佈式事務分拆成多個僅處於單個數據庫上面的小事務,並經過應用程序來總控各個小事務。固然,這樣做的要求就是咱們的俄應用程序必需要有足夠的健壯性,固然也會給應用程序帶來一些技術難度。

2.跨節點Join的問題

推薦經過應用程序來進行處理,先在驅動表所在的MySQLServer中取出相應的驅動結果集,而後根據驅動結果集再到被驅動表所在的MySQL Server中取出相應的數據。

3.跨節點合併排序分頁問題

從多個數據源並行的取數據,而後應用程序彙總處理。

9、可擴展性設計之CacheSearch的利用

經過引入Cache(Redis、Memcached),減小數據庫的訪問,增長性能。

經過引入Search(Lucene、Solr、ElasticSearch),利用搜索引擎高效的全文索引和分詞算法,以及高效的數據檢索實現,來解決數據庫和傳統的Cache軟件徹底沒法解決的全文模糊搜索、分類統計查詢等功能。

 

本文乃《MySQL性能調優與架構設計》讀書筆記!

《MySQL性能優化的最佳20+條經驗》 http://coolshell.cn/articles/1846.html

 

 

不會使用索引,致使全表掃描狀況

1.不要使用in操做符,這樣數據庫會進行全表掃描,
推薦方案:在業務密集的SQL當中儘可能不採用IN操做符

2.not in 使用not in也不會走索引
推薦方案:用not exists或者(外聯結+判斷爲空)來代替

3<> 操做符(不等於) 使用<>一樣不會使用索引,所以對它的處理只會產生全表掃描
推薦方案:用其它相同功能的操做運算代替,如
a<>0 改成 a>0 or a<0

a<>’’ 改成 a>’’

4.IS NULL 或IS NOT NULL操做(判斷字段是否爲空)

判斷字段是否爲空通常是不會應用索引的,由於B樹索引是不索引空值的。
推薦方案:用其它相同功能的操做運算代替,如
a is not null 改成 a>0 或a>’’等。

5.> 及 < 操做符(大於或小於操做符)

大於或小於操做符通常狀況下是不用調整的,由於它有索引就會採用索引查找,但有的狀況下能夠對它進行優化,如一個表有100萬記錄,一個數值型字段A,30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那麼執行A>2與A>=3的效果就有很大的區別了,由於A>2時ORACLE會先找出爲2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄索引。

6.LIKE操做符

LIKE操做符能夠應用通配符查詢,裏面的通配符組合可能達到幾乎是任意的查詢,可是若是用得很差則會產生性能上的問題,如LIKE ‘%5400%’ 這種查詢不會引用索引,而LIKE ‘5400%’則會引用範圍索引。
能夠採用substr(column,1,4)=’5400’

7.UNION操做符

UNION在進行表連接後會篩選掉重複的記錄,因此在表連接後會對所產生的結果集進行排序運算,刪除重複的記錄再返回結果。實際大部分應用中是不會產生重複的記錄,最多見的是過程表與歷史表UNION。如:
select * from gc_dfys

union

select * from ls_jg_dfys

這個SQL在運行時先取出兩個表的結果,再用排序空間進行排序刪除重複的記錄,最後返回結果集,若是表數據量大的話可能會致使用磁盤進行排序。

推薦方案:採用UNION ALL操做符替代UNION,由於UNION ALL操做只是簡單的將兩個結果合併後就返回。

8.SQL書寫的影響(針對oracle而言)

同一功能同一性能不一樣寫法SQL的影響

如一個SQL在A程序員寫的爲

Select * from zl_yhjbqk

B程序員寫的爲

Select * from dlyx.zl_yhjbqk(帶表全部者的前綴)

C程序員寫的爲

Select * from DLYX.ZLYHJBQK(大寫表名)

D程序員寫的爲

Select * from DLYX.ZLYHJBQK(中間多了空格)

以上四個SQL在ORACLE分析整理以後產生的結果及執行的時間是同樣的,可是從ORACLE共享內存SGA的原理,能夠得出ORACLE對每一個 SQL都會對其進行一次分析,而且佔用共享內存,若是將SQL的字符串及格式寫得徹底相同則ORACLE只會分析一次,共享內存也只會留下一次的分析結果,這不只能夠減小分析SQL的時間,並且能夠減小共享內存重複的信息,ORACLE也能夠準確統計SQL的執行頻率。

9.WHERE後面的條件順序影響

WHERE子句後面的條件順序對大數據量表的查詢會產生直接的影響,如

Select * from zl_yhjbqk where dy_dj = '1K如下' and xh_bz=1

Select * from zl_yhjbqk where xh_bz=1 and dy_dj = '1K如下'

以上兩個SQL中dy_dj及xh_bz兩個字段都沒進行索引,因此執行的時候都是全表掃描,第一條SQL的dy_dj ='1KV如下'條件在記錄集內比率爲99%,而xh_bz=1的比率只爲0.5%,在進行第一條SQL的時候99%條記錄都進行dy_dj及xh_bz的比較,而在進行第二條SQL的時候0.5%條記錄都進行dy_dj及xh_bz的比較,以此能夠得出第二條SQL的CPU佔用率明顯比第一條低。

10.查詢表順序的影響

在FROM後面的表中的列表順序會對SQL執行性能影響,在沒有索引及ORACLE沒有對錶進行統計分析的狀況下ORACLE會按表出現的順序進行連接,由此由於表的順序不對會產生十分耗服務器資源的數據交叉。(注:若是對錶進行了統計分析,ORACLE會自動先進小表的連接,再進行大表的連接)

 

 

sql語句優化之一:儘可能使用索引避免全表掃描

1.對查詢進行優化,應儘可能避免全表掃描,首先應考慮在 where 及 order by 涉及的列上創建索引。

2.應儘可能避免在 where 子句中對字段進行 null 值判斷,不然將致使引擎放棄使用索引而進行全表掃描,如:
select id from t where num is null
能夠在num上設置默認值0,確保表中num列沒有null值,而後這樣查詢:
select id from t where num=0

3.應儘可能避免在 where 子句中使用!=或<>操做符,不然將引擎放棄使用索引而進行全表掃描。

4.應儘可能避免在 where 子句中使用 or 來鏈接條件,不然將致使引擎放棄使用索引而進行全表掃描,如:
select id from t where num=10 or num=20
能夠這樣查詢:
select id from t where num=10
union all
select id from t where num=20

5.in 和 not in 也要慎用,不然會致使全表掃描,如:
select id from t where num in(1,2,3)
對於連續的數值,能用 between 就不要用 in 了:
select id from t where num between 1 and 3

6.下面的查詢也將致使全表掃描:
select id from t where name like '%abc%'
若要提升效率,能夠考慮全文檢索。

7.若是在 where 子句中使用參數,也會致使全表掃描。由於SQL只有在運行時纔會解析局部變量,但優化程序不能將訪問計劃的選擇推遲到運行時;它必須在編譯時進行選擇。然而,若是在編譯時創建訪問計劃,變量的值仍是未知的,於是沒法做爲索引選擇的輸入項。以下面語句將進行全表掃描:
select id from t where num=@num
能夠改成強制查詢使用索引:
select id from t with(index(索引名)) where num=@num

8.應儘可能避免在 where 子句中對字段進行表達式操做,這將致使引擎放棄使用索引而進行全表掃描。如:
select id from t where num/2=100
應改成:
select id from t where num=100*2

9.應儘可能避免在where子句中對字段進行函數操做,這將致使引擎放棄使用索引而進行全表掃描。如:
select id from t where substring(name,1,3)='abc'--name以abc開頭的id
select id from t where datediff(day,createdate,'2005-11-30')=0--‘2005-11-30’生成的id
應改成:
select id from t where name like 'abc%'
select id from t where createdate>='2005-11-30' and createdate<'2005-12-1'

10.不要在 where 子句中的「=」左邊進行函數、算術運算或其餘表達式運算,不然系統將可能沒法正確使用索引。

11.在使用索引字段做爲條件時,若是該索引是複合索引,那麼必須使用到該索引中的第一個字段做爲條件時才能保證系統使用該索引,不然該索引將不會被使用,而且應儘量的讓字段順序與索引順序相一致。

12.不要寫一些沒有意義的查詢,如須要生成一個空表結構:
select col1,col2 into #t from t where 1=0
這類代碼不會返回任何結果集,可是會消耗系統資源的,應改爲這樣:
create table #t(...)

13.不少時候用 exists 代替 in 是一個好的選擇:
select num from a where num in(select num from b)
用下面的語句替換:
select num from a where exists(select 1 from b where num=a.num)

14.並非全部索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那麼即便在sex上建了索引也對查詢效率起不了做用。

15.索引並非越多越好,索引當然能夠提升相應的 select 的效率,但同時也下降了 insert 及 update 的效率,由於 insert 或 update 時有可能會重建索引,因此怎樣建索引須要慎重考慮,視具體狀況而定。一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的索引是否有必要。

14.並非全部索引對查詢都有效,SQL是根據表中數據來進行查詢優化的,當索引列有大量數據重複時,SQL查詢可能不會去利用索引,如一表中有字段sex,male、female幾乎各一半,那麼即便在sex上建了索引也對查詢效率起不了做用。
18.儘量的使用 varchar/nvarchar 代替 char/nchar ,由於首先變長字段存儲空間小,能夠節省存儲空間,其次對於查詢來講,在一個相對較小的字段內搜索效率顯然要高些。

20.儘可能使用表變量來代替臨時表。若是表變量包含大量數據,請注意索引很是有限(只有主鍵索引)。

21.避免頻繁建立和刪除臨時表,以減小系統表資源的消耗。

23.在新建臨時表時,若是一次性插入數據量很大,那麼能夠使用 select into 代替 create table,避免形成大量 log ,以提升速度;若是數據量不大,爲了緩和系統表的資源,應先create table,而後insert。

25.儘可能避免使用遊標,由於遊標的效率較差,若是遊標操做的數據超過1萬行,那麼就應該考慮改寫。


28.在全部的存儲過程和觸發器的開始處設置 SET NOCOUNT ON ,在結束時設置 SET NOCOUNT OFF 。無需在執行存儲過程和觸發器的每一個語句後向客戶端發送 DONE_IN_PROC 消息。

30.儘可能避免向客戶端返回大數據量,若數據量過大,應該考慮相應需求是否合理

 

 

drop、truncate和delete的區別

(1)DELETE語句執行刪除的過程是每次從表中刪除一行,而且同時將該行的刪除操做做爲事務記錄在日誌中保存以便進行進行回滾操做。

   TRUNCATE TABLE 則一次性地從表中刪除全部的數據並不把單獨的刪除操做記錄記入日誌保存,刪除行是不能恢復的。而且在刪除的過程當中不會激活與表有關的刪除觸發器。執行速度快。

(2)表和索引所佔空間。

   當表被TRUNCATE 後,這個表和索引所佔用的空間會恢復到初始大小,

   DELETE操做不會減小表或索引所佔用的空間。

   drop語句將表所佔用的空間全釋放掉。

(3)通常而言,drop > truncate > delete

(4)應用範圍。

    TRUNCATE 只能對TABLE;         DELETE能夠是table和view

(5)TRUNCATE 和DELETE只刪除數據, DROP則刪除整個表(結構和數據)。

(6)truncate與不帶where的delete :只刪除數據,而不刪除表的結構(定義)drop語句將刪除表的結構被依賴的約束(constrain),觸發器(trigger)索引(index);依賴於該表的存儲過程/函數將被保留,但其狀態會變爲:invalid。

(7)delete語句爲DML(data maintain Language),這個操做會被放到 rollback segment中,事務提交後才生效。若是有相應的 tigger,執行的時候將被觸發。

(8)truncate、drop是DLL(data define language),操做當即生效,原數據不放到 rollback segment中,不能回滾

(9)在沒有備份狀況下,謹慎使用 drop 與 truncate。要刪除部分數據行採用delete且注意結合where來約束影響範圍。回滾段要足夠大。要刪除表用drop;若想保留表而將表中數據刪除,若是於事務無關,用truncate便可實現。若是和事務有關,或老師想觸發trigger,仍是用delete。

(10) Truncate table 表名 速度快,並且效率高,由於: 
truncate table 在功能上與不帶 WHERE 子句的 DELETE 語句相同:兩者均刪除表中的所有行。但 TRUNCATE TABLE 比 DELETE 速度快,且使用的系統和事務日誌資源少。DELETE 語句每次刪除一行,並在事務日誌中爲所刪除的每行記錄一項。TRUNCATE TABLE 經過釋放存儲表數據所用的數據頁來刪除數據,而且只在事務日誌中記錄頁的釋放。 

(11) TRUNCATE TABLE 刪除表中的全部行,但表結構及其列、約束、索引等保持不變。新行標識所用的計數值重置爲該列的種子。若是想保留標識計數值,請改用 DELETE。若是要刪除表定義及其數據,請使用 DROP TABLE 語句。 

(12) 對於由 FOREIGN KEY 約束引用的表,不能使用 TRUNCATE TABLE,而應使用不帶 WHERE 子句的 DELETE 語句。因爲 TRUNCATE TABLE 不記錄在日誌中,因此它不能激活觸發器。

1、delete

一、delete是DML,執行delete操做時,每次從表中刪除一行,而且同時將該行的的刪除操做記錄在redo和undo表空間中以便進行回滾(rollback)和重作操做,但要注意表空間要足夠大,須要手動提交(commit)操做才能生效,能夠經過rollback撤消操做。

二、delete可根據條件刪除表中知足條件的數據,若是不指定where子句,那麼刪除表中全部記錄。

三、delete語句不影響表所佔用的extent,高水線(high watermark)保持原位置不變。

2、truncate

一、truncate是DDL,會隱式提交,因此,不能回滾,不會觸發觸發器。

二、truncate會刪除表中全部記錄,而且將從新設置高水線和全部的索引,缺省狀況下將空間釋放到minextents個extent,除非使用reuse storage,。不會記錄日誌,因此執行速度很快,但不能經過rollback撤消操做(若是一不當心把一個表truncate掉,也是能夠恢復的,只是不能經過rollback來恢復)。

三、對於外鍵(foreignkey )約束引用的表,不能使用 truncate table,而應使用不帶 where 子句的 delete 語句。

四、truncatetable不能用於參與了索引視圖的表。

3、drop

一、drop是DDL,會隱式提交,因此,不能回滾,不會觸發觸發器。

二、drop語句刪除表結構及全部數據,並將表所佔用的空間所有釋放。

三、drop語句將刪除表的結構所依賴的約束,觸發器,索引,依賴於該表的存儲過程/函數將保留,可是變爲invalid狀態。

 

總結:

一、在速度上,通常來講,drop> truncate > delete。

二、在使用drop和truncate時必定要注意,雖然能夠恢復,但爲了減小麻煩,仍是要慎重。

三、若是想刪除部分數據用delete,注意帶上where子句,回滾段要足夠大;

   若是想刪除表,固然用drop; 

   若是想保留表而將全部數據刪除,若是和事務無關,用truncate便可;

   若是和事務有關,或者想觸發trigger,仍是用delete;

   若是是整理表內部的碎片,能夠用truncate跟上reuse stroage,再從新導入/插入數據。

 

 

 

MySQL的一條慢SQL查詢致使整個網站宕機的解決方法

咱們經過觀看應用程序服務器的監控看到一些信息:咱們的 goods_service 這個服務異常:異常狀況以下:

1. cpu 長期佔用100% + 
2. jstatck pid 沒法dump 內存堆棧信息,必須強制dump -F
3. dump 出來的內存信息發現,這個進程裏邊全部線程 均處於 BLOCKED 狀態
4. 經過jstat -gcutil 看到 FGC 至關頻繁,10s左右就FGC一次
5. 內存佔用超過了分配的內存

那麼最終的緣由就是由於上邊的慢查詢 查詢了大量數據(最多有700w行數據),致使goods_service 內存暴漲,出現服務沒法響應,進一步的惡化就是掛佔


OK,知道了爲何會掛佔,那麼咱們是如何解決這個問題的呢?
既然咱們知道是因爲查詢了 ss_si_id=0 致使的,那麼咱們屏蔽掉這個SQL不就行了麼。屏蔽的辦法能夠有多種:
1. 咱們程序邏輯判斷一下這類型的 查詢 若是 有查詢 ss_si_id=0 的一概封殺掉
2. 咱們改改SQL配置文件,修改SQL語句

咱們發現DB服務器上存在大量的 這個慢查詢,並且DB服務器負載已經從 0.xx 飆升到了 50+ 了,隨之而來的鏈接數也飆升的厲害, 若是再不及時處理,估計DB服務器也掛掉了

 

那麼咱們最終採起如下處理辦法:
1.運維配合研發修改SQL語句 咱們在這個WHERE 條件中添加了一個條件: AND ss_si_id <> 0 ,在MySQL之行計劃層屏蔽掉此SQL;
2.DBA 開啓kill 掉這個查詢語句,避免DB服務器出現down機的狀況,固然這個就用到了咱們的 pt-kill 工具,不得不說這個工具至關好用

總結(經驗與教訓): 1.相似這種查詢 default 值的 SQL ,咱們應該從源頭上杜絕這類查詢 2.限制查詢結果集大小,避免因查詢結果集太大致使服務死掉

相關文章
相關標籤/搜索