接上篇??!!
2. SQL的生命周期?
(1)應(yīng)用服務(wù)器與數(shù)據(jù)庫服務(wù)器建立一個連接
(2)數(shù)據(jù)庫進程拿到請求sql
(3)解析并生成執(zhí)行計劃,執(zhí)行
(4)讀取數(shù)據(jù)到內(nèi)存并進行邏輯處理
(5)通過步驟一的連接,發(fā)送結(jié)果到客戶端
(6)關(guān)掉連接,釋放資源

3. 大表數(shù)據(jù)查詢,怎么優(yōu)化
(1)優(yōu)化shema、sql語句+索引;
(2)第二加緩存,memcached, redis;
(3)主從復(fù)制,讀寫分離;
(4)v垂直拆分,根據(jù)你模塊的耦合度,將一個大的系統(tǒng)分為多個小的系統(tǒng),也就是分布式系統(tǒng);
(5)水平切分,針對數(shù)據(jù)量大的表,這一步最麻煩,最能考驗技術(shù)水平,要選擇一個合理的sharding key, 為了有好的查詢效率,表結(jié)構(gòu)也要改動,做一定的冗余,應(yīng)用也要改,sql中盡量帶sharding key,將數(shù)據(jù)定位到限定的表上去查,而不是掃描全部的表;
4. 超大分頁怎么處理?
超大的分頁一般從兩個方向上來解決.
(1)數(shù)據(jù)庫層面,這也是我們主要集中關(guān)注的(雖然收效沒那么大),類似于select * from table where age > 20 limit 1000000,10這種查詢其實也是有可以優(yōu)化的余地的. 這條語句需要load1000000數(shù)據(jù)然后基本上全部丟棄,只取10條當然比較慢. 當時我們可以修改為select * from table where id in (select id from table where age > 20 limit 1000000,10).這樣雖然也load了一百萬的數(shù)據(jù),但是由于索引覆蓋,要查詢的所有字段都在索引中,所以速度會很快. 同時如果ID連續(xù)的好,我們還可以select * from table where id > 1000000 limit 10,效率也是不錯的,優(yōu)化的可能性有許多種,但是核心思想都一樣,就是減少load的數(shù)據(jù).
(2)從需求的角度減少這種請求…主要是不做類似的需求(直接跳轉(zhuǎn)到幾百萬頁之后的具體某一頁.只允許逐頁查看或者按照給定的路線走,這樣可預(yù)測,可緩存)以及防止ID泄漏且連續(xù)被人惡意攻擊.
解決超大分頁,其實主要是靠緩存,可預(yù)測性的提前查到內(nèi)容,緩存至redis等k-V數(shù)據(jù)庫中,直接返回即可.
在阿里巴巴《Java開發(fā)手冊》中,對超大分頁的解決辦法是類似于上面提到的第一種.
【推薦】利用延遲關(guān)聯(lián)或者子查詢優(yōu)化超多分頁場景。
說明:MySQL并不是跳過offset行,而是取offset+N行,然后返回放棄前offset行,返回N行,那當offset特別大的時候,效率就非常的低下,要么控制返回的總頁數(shù),要么對超過特定閾值的頁數(shù)進行SQL改寫。
正例:先快速定位需要獲取的id段,然后再關(guān)聯(lián):
SELECT a.* FROM 表1 a, (select id from 表1 where 條件 LIMIT 100000,20 ) b where a.id=b.id
5. mysql 分頁
LIMIT 子句可以被用于強制 SELECT 語句返回指定的記錄數(shù)。LIMIT 接受一個或兩個數(shù)字參數(shù)。參數(shù)必須是一個整數(shù)常量。如果給定兩個參數(shù),第一個參數(shù)指定第一個返回記錄行的偏移量,第二個參數(shù)指定返回記錄行的最大數(shù)目。初始記錄行的偏移量是 0(而不是 1)
mysql> SELECT * FROM table LIMIT 5,10; // 檢索記錄行 6-15
為了檢索從某一個偏移量到記錄集的結(jié)束所有的記錄行,可以指定第二個參數(shù)為 -1:
mysql> SELECT * FROM table LIMIT 95,-1; // 檢索記錄行 96-last.
如果只給定一個參數(shù),它表示返回最大的記錄行數(shù)目:
mysql> SELECT * FROM table LIMIT 5; //檢索前 5 個記錄行
換句話說,LIMIT n 等價于 LIMIT 0,n。
6. 慢查詢?nèi)罩?/b>
用于記錄執(zhí)行時間超過某個臨界值的SQL日志,用于快速定位慢查詢,為我們的優(yōu)化做參考。
開啟慢查詢?nèi)罩?/p>
配置項:slow_query_log
可以使用show variables like ‘slov_query_log’查看是否開啟,如果狀態(tài)值為OFF,可以使用set GLOBAL slow_query_log = on來開啟,它會在datadir下產(chǎn)生一個xxx-slow.log的文件。
設(shè)置臨界時間
配置項:long_query_time
查看:show VARIABLES like 'long_query_time',單位秒
設(shè)置:set long_query_time=0.5
實操時應(yīng)該從長時間設(shè)置到短的時間,即將最慢的SQL優(yōu)化掉
查看日志,一旦SQL超過了我們設(shè)置的臨界時間就會被記錄到xxx-slow.log中
7. 關(guān)心過業(yè)務(wù)系統(tǒng)里面的sql耗時嗎?統(tǒng)計過慢查詢嗎?對慢查詢都怎么優(yōu)化過?
在業(yè)務(wù)系統(tǒng)中,除了使用主鍵進行的查詢,其他的我都會在測試庫上測試其耗時,慢查詢的統(tǒng)計主要由運維在做,會定期將業(yè)務(wù)中的慢查詢反饋給我們。
慢查詢的優(yōu)化首先要搞明白慢的原因是什么?是查詢條件沒有命中索引?是load了不需要的數(shù)據(jù)列?還是數(shù)據(jù)量太大?
所以優(yōu)化也是針對這三個方向來的,
(1)首先分析語句,看看是否load了額外的數(shù)據(jù),可能是查詢了多余的行并且拋棄掉了,可能是加載了許多結(jié)果中并不需要的列,對語句進行分析以及重寫。
(2)分析語句的執(zhí)行計劃,然后獲得其使用索引的情況,之后修改語句或者修改索引,使得語句可以盡可能的命中索引。
(3)如果對語句的優(yōu)化已經(jīng)無法進行,可以考慮表中的數(shù)據(jù)量是否太大,如果是的話可以進行橫向或者縱向的分表。
8. 為什么要盡量設(shè)定一個主鍵?
主鍵是數(shù)據(jù)庫確保數(shù)據(jù)行在整張表唯一性的保障,即使業(yè)務(wù)上本張表沒有主鍵,也建議添加一個自增長的ID列作為主鍵。設(shè)定了主鍵之后,在后續(xù)的刪改查的時候可能更加快速以及確保操作數(shù)據(jù)范圍安全。
最后,小編分類整理了許多java進階學(xué)習(xí)材料和BAT面試給熱愛IT行業(yè)的你,如果需要資料的請轉(zhuǎn)發(fā)此文章后再私聊小編回復(fù)【java】就能領(lǐng)取2019年java進階學(xué)習(xí)資料和BAT面試題以及《Effective Java》(第3版)電子版書籍。也可以加群:712263501領(lǐng)取海量學(xué)習(xí)資料進行學(xué)習(xí)。