查詢在每個 MySQL 數(shù)據(jù)庫管理員甚至精通數(shù)據(jù)庫的開發(fā)人員的生活中無處不在。正如我們在之前的一些博客文章中已經(jīng)指出的那樣,查詢只是由較小任務組成的任務。為了優(yōu)化它們的性能,我們應該讓那些較小的任務執(zhí)行得更快或者根本不執(zhí)行。首先,我們必須檢查 MySQL 如何執(zhí)行查詢。
什么是查詢緩存?
MySQL 查詢緩存雖然在 MySQL 5.7 中被棄用(并在 8.0 中刪除),但存儲以前在內(nèi)存中運行的語句:換句話說,查詢緩存通常將SELECT語句存儲在數(shù)據(jù)庫的內(nèi)存中。因此,如果我們運行一個查詢,然后在一段時間后再次運行完全相同的查詢,結果將更快地返回,因為它們將從內(nèi)存而不是從磁盤中檢索。
查詢緩存緩存查詢和結果集。因此,當我們運行相同的查詢時,查詢緩存的結果會立即返回。查詢緩存大小可以通過設置query_cache_size系統(tǒng)變量來控制,但這里有一個警告:如果您希望查詢使用查詢緩存,它們必須,必須,必須相同,逐字節(jié)。這意味著即使您認為這兩個查詢應該以完全相同的方式緩存:
SELECT * FROM demo_table WHERE column = 'Demo';
select * from demo_table where column = 'Demo';
事實上,他們不是。它們不是因為 MySQL 查詢緩存要求其所有查詢都相同,并且即使它們相差一個字節(jié)也不會返回任何結果。
所以,總結一下,當 MySQL 執(zhí)行語句時,它做的第一件事就是檢查是否啟用了查詢緩存(如果需要復習,請回到我們上一篇關于慢速 MySQL 查詢的博客文章。)如果查詢緩存啟用后,MySQL 將首先檢查與該查詢的任何相關匹配項;如果沒有匹配項,MySQL 將繼續(xù)下一步。但是,如果存在相同的匹配項,MySQL 將從其查詢緩存中返回結果。
MySQL內(nèi)部的查詢緩存
在此之前返回比賽,MySQL的查詢緩存要求MySQL的確認:d OES該用戶有必要的權限才能完成這樣的動作?我應該拒絕執(zhí)行查詢嗎?
以下是 MySQL 檢查的權限列表:
特權 | 簡要說明 |
---|---|
ALL | 賦予特定 MySQL 用戶所有權限。 |
SELECT | 授予特定 MySQL 用戶從指定數(shù)據(jù)庫中選擇行的權限。 |
UPDATE | 授予特定 MySQL 用戶更新指定表中現(xiàn)有行的權限。 |
SHOW DATABASES | 使特定 MySQL 用戶能夠獲取存在于一個特定 MySQL 實例中的所有 MySQL 數(shù)據(jù)庫的列表。 |
USAGE | 賦予用戶僅使用 MySQL 的權力,這意味著用戶不能在其中運行任何查詢。本質(zhì)上是無特權的同義詞。 |
有更多的特權,但你明白了。權限對于查詢緩存很重要,因為 MySQL 還將與表相關的信息與緩存查詢一起存儲。權限也很重要,因為它是 MySQL 結果檢查過程的第一階段之一。這是一切的工作原理:
優(yōu)先識別 | MYSQL 狀態(tài) | 解釋 |
---|---|---|
1 | MySQL 正在檢查查詢緩存中的權限。 | 首先,MySQL 檢查特定用戶是否有權訪問特定結果。 |
2 | MySQL 正在檢查查詢本身的查詢緩存。 | 接下來,MySQL 開始檢查查詢緩存中是否存在相同的查詢。如果匹配,MySQL 返回;如果沒有,MySQL 繼續(xù)下一步。 |
3 | MySQL 將查詢緩存中的條目標記為無效。 | 隨著表的變化,查詢緩存需要更新。所以在這一步中,MySQL 決定將查詢緩存中的條目標記為無效。 |
4 | 發(fā)送結果。 | MySQL 發(fā)送緩存的結果并顯示它。 |
5 | 將結果存儲在緩存中。 | MySQL 將查詢結果保存在查詢緩存中。 |
6 | 查詢緩存被鎖定。 | 緩存過程現(xiàn)在結束——MySQL 鎖定查詢緩存。 |
“MySql沒有緩存!”:要看查詢緩存是否損壞?
當使用函數(shù)或分區(qū)時,如果我們在查詢中使用任何變量,查詢緩存也將無效。例如,如果我們正在處理大數(shù)據(jù),并且我們使用SELECT ... INTO OUTFILE將大數(shù)據(jù)集加載到 MySQL 中,則結果同樣不會被緩存。通常,查詢緩存SELECT ... [LOCK | FOR | INTO]在使用類似查詢時不起作用,如果我們正在檢查具有NULL值的列中的AUTO_INCREMENT值,則查詢緩存也無法使用,這意味著如果我們有一個increment帶有 的列AUTO_INCREMENT,并且我們運行這樣的查詢所以:
SELECT * FROM demo_table WHERE increment IS NULL;
查詢緩存也不會生效。
所有這些功能可能會讓你們中的一些人大喊“它不起作用!” - 你是對的。查詢緩存并不總是有效:與 MySQL 中的所有內(nèi)容一樣,它也有局限性。除了上述那些,當語句生成警告或語句在帶有TEMPORARY存儲引擎的表上運行時以及在其他一些極端情況下,它拒絕工作。每次有人向表寫入任何內(nèi)容時,查詢緩存也會清空。
查詢緩存的功能也取決于query_cache_size參數(shù)。此參數(shù)越大越好,但請注意,此參數(shù)在很大程度上取決于您的內(nèi)存。請記住,查詢緩存的基本結構默認至少需要 40kB 的存儲空間,其默認值可能在 1MB 到 16MB 之間。但是,如果您的數(shù)據(jù)庫非常忙于讀取數(shù)據(jù),則更大的值可能有助于找到最佳解決方案,您必須再次進行試驗。
您還可以通過運行該RESET QUERY CACHE語句來刪除查詢緩存中的所有內(nèi)容。如果您使用類似 的語句FLUSH TABLES,所有值也將從查詢緩存中刪除。
MySQL 甚至允許您通過運行查詢來查看查詢緩存中存儲了多少查詢:
SHOW STATUS LIKE 'Qcache_queries_in_cache%';
您會得到如下所示的結果:
MySQL:
+-------------------------+--------+
| Variable_name | Value |
+-------------------------+--------+
| Qcache_queries_in_cache | 1 |
+-------------------------+--------+
在這種情況下,我們可以看到我們的查詢緩存當前緩存了一個結果。執(zhí)行類似的語句FLUSH TABLES,所有值都將消失。
總結
在 MySQL 中,查詢緩存是一個非常強大的野獸。它通常能夠存儲各種各樣的值并從內(nèi)存中返回它們,而不是從磁盤中返回它們,以加快查詢執(zhí)行時間。然而,它并非沒有缺陷。查詢緩存有一些限制,但如果您知道自己在做什么,應該沒問題。
查詢緩存對于SELECT查詢最有用的。