1. 程式人生 > >Mysql面試題及千萬級資料查詢優化

Mysql面試題及千萬級資料查詢優化

今天在說Mysql查詢優化之前,我先說一個常見的面試題,並帶著問題深入探討研究。這樣會讓大家有更深入的理解。

一,Mysql資料庫中一個表裡有一千多萬條資料,怎麼快速的查出第900萬條後的100條資料?

怎麼查,誰能告訴我答案?有沒有人想著,不就一條語句搞定嘛

select * from table limit 9000000,100;

那我們試試,去執行下這個SQL看看吧

 

 

看見了嗎,查了100條資料用了7.063s。這能算的上是快速查詢嗎,估計沒人能接受了這種速度吧!基於這個問題,我今天就要說說大資料時的快速查詢了。

 

 


首先,我演示下大資料分頁查詢,我的test表裡有1000多萬條資料,然後使用limit進行分頁測試:select * from test limit 0,100;

耗時:0.005s

select * from test limit 1000,100;

耗時:0.006s

select * from test limit 10000,100;

耗時:0.013s

select * from test limit 100000,100;

耗時:0.104s

select * from test limit 500000,100;

耗時:0.395s

select * from test limit 1000000,100;

耗時:0.823s

select * from test limit 5000000,100;

耗時:3.909s

select * from test limit 10000000,100;

耗時:10.761s

我們發現一個現象,分頁查詢越靠後查詢越慢。這也讓我們得出一個結論:

1,limit語句的查詢時間與起始記錄的位置成正比。

2,mysql的limit語句是很方便,但是對記錄很多的表並不適合直接使用。

對大資料量limit分頁效能優化

說到查詢優化,我們首先想到的肯定是使用索引。利用了索引查詢的語句中如果條件只包含了那個索引列,那在這種情況下查詢速度就很快了。因為利用索引查詢有相應的優化演算法,且資料就在查詢索引上面,不用再去找相關的資料地址了,這樣節省了很多時間。另外Mysql中也有相關的索引快取,在併發高的時候利用快取就效果更好了。

我的test表使用InnoDB作為儲存引擎,id作為自增主鍵,預設為主鍵索引。那我們現在用覆蓋索引查詢,看看效果如何:

SELECT id FROM test LIMIT 9000000,100;

總耗時4.256s,相對於7.063s少了很多。
現在優化的方案有兩種,即通過id作為查詢條件使用子查詢實現和使用join實現;
1,id>=的(子查詢)形式實現

select * from test where id >= (select id from test limit 9000000,1)limit 0,100 

耗時 4.262s;

2,使用join的形式;

SELECT * FROM test a JOIN (SELECT id  FROM test LIMIT 9000000,100) b ON a.id = b.id

耗時 4.251s;這兩種優化查詢使用時間比較接近,其實兩者用的都是一個原理,所以效果也差不多。但個人建議最好使用join,儘量減少子查詢的使用。注:目前是千萬級別查詢,如果將至百萬級別,速度會更快,我有親自測試一下語句,查詢時間0.410s。

SELECT * FROM test a JOIN (SELECT id  FROM test LIMIT 1000000,100) b ON a.id = b.id

 

二,你用過mysql那些儲存引擎,他們都有什麼特點和區別?

這是高階開發者面試時經常被問的問題。實際我們在平時的開發中,經常會遇到的,在用SQLyog等工具建立表時,就有一個引擎項要你去選。如下圖:

 

 

Mysql的儲存引擎有這麼多種,實際我們在平時用的最多的莫過於InnoDB和MyISAM了。所有如果面試官問道mysql有哪些儲存引擎,你只需要告訴這兩個常用的就行。那他們都有什麼特點和區別呢?MyISAM:預設表型別,它是基於傳統的ISAM型別,ISAM是Indexed Sequential Access Method (有索引的順序訪問方法) 的縮寫,它是儲存記錄和檔案的標準方法。不是事務安全的,而且不支援外來鍵,如果執行大量的select,insert MyISAM比較適合。InnoDB:支援事務安全的引擎,支援外來鍵、行鎖、事務是他的最大特點。如果有大量的update和insert,建議使用InnoDB,特別是針對多個併發和QPS較高的情況。注:在MySQL 5.5之前的版本中,預設的搜尋引擎是MyISAM,從MySQL 5.5之後的版本中,預設的搜尋引擎變更為InnoDB。MyISAM和InnoDB的區別:

1,InnoDB支援事務,MyISAM不支援。對於InnoDB每一條SQL語言都預設封裝成事務,自動提交,這樣會影響速度,所以最好把多條SQL語言放在begin和commit之間,組成一個事務; 

2,InnoDB支援外來鍵,而MyISAM不支援。

3,InnoDB是聚集索引,使用B+Tree作為索引結構,資料檔案是和(主鍵)索引綁在一起的(表資料檔案本身就是按B+Tree組織的一個索引結構),必須要有主鍵,通過主鍵索引效率很高。MyISAM是非聚集索引,也是使用B+Tree作為索引結構,索引和資料檔案是分離的,索引儲存的是資料檔案的指標。主鍵索引和輔助索引是獨立的。

4,InnoDB不儲存表的具體行數,執行select count(*) from table時需要全表掃描。而MyISAM用一個變數儲存了整個表的行數,執行上述語句時只需要讀出該變數即可,速度很快。

5,Innodb不支援全文索引,而MyISAM支援全文索引,查詢效率上MyISAM要高;5.7以後的InnoDB支援全文索引了。

6,InnoDB支援表、行級鎖(預設),而MyISAM支援表級鎖。;

7,InnoDB表必須有主鍵(使用者沒有指定的話會自己找或生產一個主鍵),而Myisam可以沒有。

8,Innodb儲存檔案有frm、ibd,而Myisam是frm、MYD、MYI。

       Innodb:frm是表定義檔案,ibd是資料檔案。

  Myisam:frm是表定義檔案,myd是資料檔案,myi是索引檔案。

三,Mysql複雜查詢語句的優化,你會怎麼做?

說到複雜SQL優化,最多的是由於多表關聯造成了大量的複雜的SQL語句,那我們拿到這種sql到底該怎麼優化呢,實際優化也是有套路的,只要按照套路執行就行。複雜SQL優化方案:

1,使用EXPLAIN關鍵詞檢查SQL。EXPLAIN可以幫你分析你的查詢語句或是表結構的效能瓶頸,就得EXPLAIN 的查詢結果還會告訴你你的索引主鍵被如何利用的,你的資料表是如何被搜尋和排序的,是否有全表掃描等;

2,查詢的條件儘量使用索引欄位,如某一個表有多個條件,就儘量使用複合索引查詢,複合索引使用要注意欄位的先後順序。

3,多表關聯儘量用join,減少子查詢的使用。表的關聯欄位如果能用主鍵就用主鍵,也就是儘可能的使用索引欄位。如果關聯欄位不是索引欄位可以根據情況考慮新增索引。

4,儘量使用limit進行分頁批量查詢,不要一次全部獲取。

5,絕對避免select *的使用,儘量select具體需要的欄位,減少不必要欄位的查詢;

6,儘量將or 轉換為 union all。

7,儘量避免使用is null或is not null。

8,要注意like的使用,前模糊和全模糊不會走索引。

9,Where後的查詢欄位儘量減少使用函式,因為函式會造成索引失效。

10,避免使用不等於(!=),因為它不會使用索引。

11,用exists代替in,not exists代替not in,效率會更好;

12,避免使用HAVING子句, HAVING 只會在檢索出所有記錄之後才對結果集進行過濾,這個處理需要排序,總計等操作。如果能通過WHERE子句限制記錄的數目,那就能減少這方面的開銷。

13,千萬不要 ORDER BY RAND() 

接下來會繼續總結一些面試中的問題共享給大家,如果覺得內容不錯請關注此公眾號,我會不定期的推送一些乾貨給大家。

 

推薦閱讀:

Api介面文件管理工具,你知道哪些呢?

Java專案支付寶支付接入及詳解

微信支付之掃碼、APP、小程式支付接入詳解

 

掃碼關注公眾號,傳送關鍵詞獲取相關資料:

  1. 傳送“Springboot”領取電商專案實戰原始碼;

  2. 傳送“SpringCloud”領取cloud學習實戰資料;

 

&n