共計 3234 個字符,預計需要花費 9 分鐘才能閱讀完成。
這篇文章主要介紹了 mysql hint 的概念是什么的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇 mysql hint 的概念是什么文章都會有所收獲,下面我們一起來看看吧。
在 mysql 中,hint 指的是“查詢優化提示”,會提示優化器按照一定的方式來生成執行計劃進行優化,讓用戶的 sql 語句更具靈活性;Hint 可基于表的連接順序、方法、訪問路徑、并行度等規則對 DML(數據操縱語言,Data Manipulation Language)語句產生作用。
本教程操作環境:windows7 系統、mysql8 版本、Dell G3 電腦。
我們在操作表、字段或索引時可以添加 comment 來增強代碼可讀性,以便他人快速讀懂代碼,這是對使用數據庫的人的一種提示;同樣的,還有一種提示,叫做 hint,是給數據庫的提示。
何謂 hint
hint 指的是“查詢優化提示”,它會提示優化器按照一定的方式去優化,讓你的 sql 語句更具靈活性,這會讓你的查詢更快,當然也可能更慢,這完全取決于你對優化器的理解和場景的了解。
我們知道在執行一條 SQL 語句時,MySQL 會生成一個執行計劃,而 hint 就是告訴查詢優化器需要按照我們告訴它的方式來生成執行計劃。
Hint 可基于表的連接順序、方法、訪問路徑、并行度等規則對 DML(數據操縱語言,Data Manipulation Language)語句產生作用,范圍如下:
使用的優化器類型;基于代價的優化器的優化目標,是 all_rows 還是 first_rows;表的訪問路徑,是全表掃描,還是索引掃描,還是直接用 rowid;表之間的連接類型;表之間的連接順序;語句的并行程度;
常用 hint
強制索引 FORCE INDEX
SELECT * FROM tbl FORCE INDEX (FIELD1) …
忽略索引 IGNORE INDEX
SELECT * FROM tbl IGNORE INDEX (FIELD1, FIELD2) …
關閉查詢緩沖 SQL_NO_CACHE
SELECT SQL_NO_CACHE field1, field2 FROM tbl;
需要查詢實時數據且頻率不高時,可以考慮把緩沖關閉,即不論此 SQL 是否曾被執行,MySQL 都不會在緩沖區中查找。
強制查詢緩沖 SQL_CACHE
SELECT SQL_CACHE * FROM tbl;
功能同上一條相反,但僅在 my.ini 中的 query_cache_type 設為 2 時起作用。
優先操作 HIGH_PRIORITY
HIGH_PRIORITY 可以使用在 select 和 insert 操作中,讓 MYSQL 知道,這個操作優先進行。
SELECT HIGH_PRIORITY * FROM tbl;
滯后操作 LOW_PRIORITY
LOW_PRIORITY 可以使用在 insert 和 update 操作中,讓 mysql 知道,這個操作滯后。
update LOW_PRIORITY tbl set field1= where field1= …
延時插入 INSERT DELAYED
INSERT DELAYED INTO tbl set field1= …
指客戶端提交插入數據申請,MySQL 返回 OK 狀態卻并未實際執行,而是存儲在內存中排隊,當 mysql 有空余時再插入。
一個重要的好處是,來自多個客戶端的插入請求被集中在一起,編寫入一個塊,比獨立執行許多插入要快很多。
壞處是,不能返回自增 ID,以及系統崩潰時,MySQL 還未來得及被插入的數據將會丟失。
強制連接順序 STRAIGHT_JOIN
SELECT tbl.FIELD1, tbl2.FIELD2 FROM tbl STRAIGHT_JOIN tbl2 WHERE …
由上面的 SQL 語句可知,通過 STRAIGHT_JOIN 強迫 MySQL 按 tbl、tbl2 的順序連接表。如果你認為按自己的順序比 MySQL 推薦的順序進行連接的效率高的話,就可以通過 STRAIGHT_JOIN 來確定連接順序。
不常用
強制使用臨時表 SQL_BUFFER_RESULT
SELECT SQL_BUFFER_RESULT * FROM tbl WHERE …
當我們查詢的結果集中的數據比較多時,可以通過 SQL_BUFFER_RESULT. 選項強制將結果集放到臨時表中,這樣就可以很快地釋放 MySQL 的表鎖(這樣其它的 SQL 語句就可以對這些記錄進行查詢了),并且可以長時間地為客戶端提供大記錄集。
分組使用臨時表 SQL_BIG_RESULT 和 SQL_SMALL_RESULT
SELECT SQL_BUFFER_RESULT FIELD1, COUNT(*) FROM tbl GROUP BY FIELD1;
對 SELECT 語句有效,告訴 MySQL 優化去對 GROUP BY 和 DISTINCT 查詢如何使用臨時表排序,SQL_SMALL_RESULT 表示結果集很小,可以直接在內存的臨時表排序;反之則很大,需要使用磁盤臨時表排序。
SQL_CALC_FOUND_ROWS
它其實不是優化器提示,也不影響優化器的執行計劃,但會讓 mysql 返回的結果集中包含本次操作影響的總行數,需與 FOUND_ROWS() 聯用。
SQL_CALC_FOUND_ROWS 通知 MySQL 將本次處理的行數記錄下來;FOUND_ROWS() 用于取出被記錄的行數,可以應用到分頁場景。
一般的分頁寫法為:先查總數,計算頁數,再查詢某一頁的詳情。
SELECT COUNT(*) from tbl WHERE …
SELECT * FROM tbl WHERE … limit m,n
但借助 SQL_CALC_FOUND_ROWS,可以簡化成如下寫法:
SELECT SQL_CALC_FOUND_ROWS * FROM tbl WHERE … limit m,n;
SELECT FOUND_ROWS();
第二條 SELECT 將返回第一條 SELECT 不帶 limit 時的總行數,如此只需執行一次較耗時的復雜查詢就可同時得到總行數。
LOCK IN SHARE MODE、FOR UPDATE
同樣的,這倆也不是優化提示,是控制 SELECT 語句的鎖機制,只對行級鎖有效,即 InnoDB 支持。
擴展知識:
概念和區別
SELECT … LOCK IN SHARE MODE 添加的是 IS 鎖(意向共享鎖),即在符合條件的 rows 上都加了共享鎖,其他 session 可讀取記錄,亦可繼續添加 IS 鎖,但無法修改,直到這個加鎖的 session done(否則直接鎖等待超時)。
SELECT … FOR UPDATE 添加的是 IX 鎖 (意向排它鎖),即符合條件的 rows 上都加了排它,其他 session 無法給這些記錄添加任何 S 鎖或 X 鎖。如果不存在一致性非鎖定讀的話,則其他 session 是無法讀取和修改這些記錄的,但 innodb 有非鎖定讀(快照讀不需要加鎖)。
因此,for update 的加鎖方式只是比 lock in share mode 的方式多阻塞了 select…lock in share mode 的查詢方式,并不會阻塞快照讀。
應用場景
LOCK IN SHARE MODE 的適用于兩張存在關系的表的寫場景,以 mysql 官方例子來說,一個表是 child 表,一個是 parent 表,假設 child 表的某一列 child_id 映射到 parent 表的 c_child_id 列,從業務角度講,此時直接 insert 一條 child_id=100 記錄到 child 表是存在風險的,因為 insert 的同時可能存在 parent 表執行了刪除 c_child_id=100 的記錄,業務數據有不一致的風險。正確方法是先執行 select * from parent where c_child_id=100 lock in share mode,鎖定 parent 表的這條記錄,然后執行 insert into child(child_id) values (100)。
關于“mysql hint 的概念是什么”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“mysql hint 的概念是什么”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注丸趣 TV 行業資訊頻道。