MySQL基礎(七):索引與慢查詢優化(未學好)

下面是小凰凰的簡介,看下吧!
💗人生態度:珍惜時間,渴望學習,熱愛音樂,把握命運,享受生活
💗學習技能:網絡 -> 雲計算運維 -> python全棧( 當前正在學習中)
💗您的點贊、收藏、關注是對博主創作的最大鼓勵,在此謝過!
有相關技能問題可以寫在下方評論區,我們一起學習,一起進步。
後期會不斷更新python全棧學習筆記,秉着質量博文爲原則,寫好每一篇博文。

一、索引

1、爲何要有索引

知識回顧:數據都是存在硬盤上的,那查詢數據不可避免的需要進行IO操作

索引在MySQL中也叫做“鍵”,是存儲引擎用於快速找到記錄的一種數據結構。

primary key

unique key

index key

注意foreign key不是用來加速查詢用的,不在我們研究範圍之內,上面三種key前兩種除了有加速查詢的效果之外還有額外的約束條件(primary key:非空且唯一,unique key:唯一),而index key沒有任何約束功能只會幫你加速查詢

索引就是一種數據結構,類似於書的目錄。意味着以後再查數據應該先找目錄再找數據,而不是用翻頁的方式查詢數據

2、什麼是索引

通過不斷地縮小想要獲取數據的範圍來篩選出最終想要的結果,同時把隨機的事件變成順序的事件,有點類似於二分法查找的機理

也就是說,有了這種索引機制,我們可以總是用同一種查找方式來鎖定數據

3、索引的影響

  • 在表中有大量數據的前提下,創建索引速度會很慢
  • 在索引創建完畢後,對錶的查詢性能會大幅度提升,但是寫的性能會降低

爲什麼說表中有大量數據,創建索引會很慢?

答:假設你現在表中數據已經很多,如果你執行增、刪、改任何一個操作,都會造成索引重新創建。
# 也即是你寫好的已經創建目錄的一本書,如果你想要添加一頁內容,那麼會造成目錄全部丟失,需要重頭一頁一頁創建索引,因此表數據很大,會造成創建索引很慢。

目前我所知道的解決方法:分庫分表

4、索引的數據結構

在這裏插入圖片描述只有葉子結點存放真實數據,根和樹枝節點存的僅僅是虛擬數據.這裏採用多級索引,索引是犧牲空間,加快速度!

磁盤塊索引詳解:https://blog.csdn.net/weixin_44571270/article/details/105899656

查詢次數由樹的層級決定,層級越低次數越少

一個磁盤塊兒的大小是一定的,那也就意味着能存的數據量是一定的。如何保證樹的層級最低呢?一個磁盤塊應該儘量用來存儲數據,而不是索引,因此添加索引的字段名應該儘量的小!

5、聚集索引、輔助索引

(1)聚集索引(primary key)

聚集索引其實指的就是表的主鍵,innodb引擎規定一張表中必須要有主鍵。先來回顧一下存儲引擎。

myisam在建表的時候對應到硬盤有幾個文件(三個)?

innodb在建表的時候對應到硬盤有幾個文件(兩個)?frm文件只存放表結構,不可能放索引,也就意味着innodb的索引跟數據都放在idb表數據文件中。

建表文件對比:https://blog.csdn.net/weixin_44571270/article/details/106710860

特點:葉子結點放的一條條完整的記錄

# 聚集索引好處
1、它對主鍵的排序查找和範圍查找速度非常快,葉子節點的數據就是用戶所要查詢的數據。

2、範圍查詢(range query),即如果要查找主鍵某一範圍內的數據,通過葉子節點的上層中間節點就可以得到頁的範圍,之後直接讀取數據頁即可
(2)輔助索引(unique,index)

輔助索引:查詢數據的時候不可能都是用id作爲篩選條件,也可能會用name,password等字段信息,那麼這個時候就無法利用到聚集索引的加速查詢效果。就需要給其他字段建立索引,這些索引就叫輔助索引

特點:輔助索引的葉子結點存放的是輔助索引建立的字段所在的那張表的主鍵的聚集索引數據塊的地址

查找流程:當通過輔助索引查找時,先通過輔助索引,獲取聚集索引,再通過聚集索引查找到相應的數據。

輔助索引又分爲覆蓋索引和非覆蓋索引:

  • 覆蓋索引
    下面語句叫覆蓋索引:只在輔助索引的葉子節點中就已經找到了所有我們想要的數據
select name from user where name='jason';
  • 非覆蓋索引
    下面語句叫非覆蓋索引,雖然查詢的時候命中了索引字段name,但是要查的是age字段,所以還需要利用聚集索引去查找!
select age from user where name='jason';

二、慢查詢優化

1、查詢優化神器

關於explain命令相信大家並不陌生,具體用法和字段含義可以參考官網explain-output,這裏需要強調rows是核心指標,絕大部分rows小的語句執行一定很快(有例外,下面會講到)。所以優化語句基本上都是在優化rows。

執行計劃:讓mysql預估執行操作(一般正確)
    all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
    id,email
    
    慢:
        select * from userinfo3 where name='alex'
        
        explain select * from userinfo3 where name='alex'
        type: ALL(全表掃描)
            select * from userinfo3 limit 1;
    快:
        select * from userinfo3 where email='alex'
        type: const(走索引)

2、慢查詢優化的基本步驟

0.先運行看看是否真的很慢,注意設置SQL_NO_CACHE
1.where條件單表查,鎖定最小返回記錄表。這句話的意思是把查詢語句的where都應用到表中返回的記錄數最小的表開始查起,單表每個字段分別查詢,看哪個字段的區分度最高
2.explain查看執行計劃,是否與1預期一致(從鎖定記錄較少的表開始查詢)
3.order by limit 形式的sql語句讓排序的表優先查
4.瞭解業務方使用場景
5.加索引時參照建索引的幾大原則
6.觀察結果,不符合預期繼續從0分析

3、慢日誌管理

        慢日誌
            - 執行時間 > 10
            - 未命中索引
            - 日誌文件路徑
            
        配置:
            - 內存
                show variables like '%query%';
                show variables like '%queries%';
                set global 變量名 =- 配置文件
                mysqld --defaults-file='E:\wupeiqi\mysql-5.7.16-winx64\mysql-5.7.16-winx64\my-default.ini'
                
                my.conf內容:
                    slow_query_log = ON
                    slow_query_log_file = D:/....
                    
                注意:修改配置文件之後,需要重啓服務
MySQL日誌管理
========================================================
錯誤日誌: 記錄 MySQL 服務器啓動、關閉及運行錯誤等信息
二進制日誌: 又稱binlog日誌,以二進制文件的方式記錄數據庫中除 SELECT 以外的操作
查詢日誌: 記錄查詢的信息
慢查詢日誌: 記錄執行時間超過指定時間的操作
中繼日誌: 備庫將主庫的二進制日誌複製到自己的中繼日誌中,從而在本地進行重放
通用日誌: 審計哪個賬號、在哪個時段、做了哪些事件
事務日誌或稱redo日誌: 記錄Innodb事務相關的如事務執行時間、檢查點等
========================================================
============================ bin-log日誌管理 ============================
1. 啓用
# vim /etc/my.cnf
[mysqld]
log-bin[=dir\[filename]]
# service mysqld restart
2. 暫停
//僅當前會話
SET SQL_LOG_BIN=0;
SET SQL_LOG_BIN=1;
3. 查看
查看全部:
# mysqlbinlog mysql.000002
按時間:
# mysqlbinlog mysql.000002 --start-datetime="2012-12-05 10:02:56"
# mysqlbinlog mysql.000002 --stop-datetime="2012-12-05 11:02:54"
# mysqlbinlog mysql.000002 --start-datetime="2012-12-05 10:02:56" --stop-datetime="2012-12-05 11:02:54" 

按字節數:
# mysqlbinlog mysql.000002 --start-position=260
# mysqlbinlog mysql.000002 --stop-position=260
# mysqlbinlog mysql.000002 --start-position=260 --stop-position=930
4. 截斷bin-log(產生新的bin-log文件)
a. 重啓mysql服務器
b. # mysql -uroot -p123 -e 'flush logs'
5. 刪除bin-log文件
# mysql -uroot -p123 -e 'reset master' 


============================ 查詢日誌管理 =============================
啓用通用查詢日誌
# vim /etc/my.cnf
[mysqld]
log[=dir\[filename]]
# service mysqld restart

============================ 慢查詢日誌管理 ===========================
啓用慢查詢日誌
# vim /etc/my.cnf
[mysqld]
log-slow-queries[=dir\[filename]]
long_query_time=n
# service mysqld restart
MySQL 5.6:
slow-query-log=1
slow-query-log-file=slow.log
long_query_time=3
查看慢查詢日誌
測試:BENCHMARK(count,expr)
SELECT BENCHMARK(50000000,2*3);
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章