大多數的MySQL服務器都開啓了查詢緩存,當有很多相同的查詢被執行了多次的時候,這些查詢結果會被放到一個緩存中,這樣,後續的相同的查詢就不用操作表而直接訪問緩存結果了
// 如果在sql語句中直接使用一些動態的函數查詢緩存不開啓 $r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()"); // 開啓查詢緩存 $today = date("Y-m-d"); $r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");
如果不想使用緩存,可以在每次查詢時直接加參數SQL_NO_CACHE來禁止使用緩存
SQL_NO_CACHE解釋如下:
select SQL_NO_CACHE picname, smallimg from pics where user_id=17853;
exists對外表用loop逐條查詢,每次查詢都會查看exists的條件語句,當exists裏的條件語句能夠返回記錄行時(無論記錄行是的多少,只要能返回)),條件就爲真,返回當前loop到的這條記錄,反之如果exists裏的條件語句不能返回記錄行,則當前loop到的這條記錄被丟棄,exists的條件就像一個bool條件,當能返回結果集則爲true,不能返回結果集則爲 false。
//每查一條記錄都會判斷後面子查詢返回的數據是否存在 SELECT SQL_NO_CACHE * FROM new_component WHERE EXISTS (SELECT new_dashboard.id FROM new_dashboard where new_dashboard.id = new_component.dashboard_id);
in查詢相當於多個or條件的疊加
SELECT SQL_NO_CACHE * FROM new_component WHERE new_component.dashboard_id IN (SELECT id FROM new_dashboard);
考慮下面兩條sql:
(1)select * from A where exists (select * from B where B.id = A.id); (2)select * from A where A.id in (select id from B);
-- (1)in操作 select SQL_NO_CACHE * from new_component where type in ('comment', 'rect', 'indicator'); -- (2)or操作 select SQL_NO_CACHE * from new_component where type = 'comment' or type = 'rect' or type = 'indicator'; -- (3)union all操作 select SQL_NO_CACHE * from new_component where type = 'comment' UNION all select * from new_component where type = 'rect' UNION all select * from new_component where type = 'indicator' UNION all select * from new_component where type = 'indicator'; -- (4)union操作 select SQL_NO_CACHE * from new_component where type = 'comment' UNION select * from new_component where type = 'rect' UNION select * from new_component where type = 'indicator' UNION select * from new_component where type = 'indicator';
# 1. merge 算法會把視圖中的sql合併到查詢的sql中,和C語言中的宏展開有點類似,這個時候和普通查詢沒什麼區別,但是不是任何時候都可以使用merge算法的,有些時候包含了聚合函數/group by/having就不能使用merge算法 # 2. temptable 算法,先執行視圖定義,將其結果保存在臨時表裏,後續操作都以這個臨時表爲準,此時會造成丟失索引,並且存在臨時表中間態,性能開銷較大
show processlist 顯示用戶正在運行的線程,需要注意的是,除了 root 用戶能看到所有正在運行的線程外,其他用戶都只能看到自己正在運行的線程,看不到其它用戶正在運行的線程。除非單獨個這個用戶賦予 PROCESS 權限。
當遇到 sql 查詢超時或者慢查詢時,我們可以使用 show processlist 命令來查詢是哪些sql查詢影響到了我們的業務的正常運行,這樣我們可以針對特定的慢查詢sql做優化。show processlist 顯示的信息都是來自MySQL系統庫 information_schema 中的 processlist 表。所以下面兩條語句返回的結果一樣:
select * from information_schema.processlist; show processlist;
執行 show processlist 命令返回的結果如下圖:
我們解釋一下每個字段的含義:
- Binlog Dump: 主節點正在將二進制日誌 ,同步到從節點 - Change User: 正在執行一個 change-user 的操作 - Close Stmt: 正在關閉一個Prepared Statement 對象 - Connect: 一個從節點連上了主節點 - Connect Out: 一個從節點正在連主節點 - Create DB: 正在執行一個create-database 的操作 - Daemon: 服務器內部線程,而不是來自客戶端的鏈接 - Debug: 線程正在生成調試信息 - Delayed Insert: 該線程是一個延遲插入的處理程序 - Drop DB: 正在執行一個 drop-database 的操作 - Execute: 正在執行一個 Prepared Statement - Fetch: 正在從Prepared Statement 中獲取執行結果 - Field List: 正在獲取表的列信息 - Init DB: 該線程正在選取一個默認的數據庫 - Kill : 正在執行 kill 語句,殺死指定線程 - Long Data: 正在從Prepared Statement 中檢索 long data - Ping: 正在處理 server-ping 的請求 - Prepare: 該線程正在準備一個 Prepared Statement - ProcessList: 該線程正在生成服務器線程相關信息 - Query: 該線程正在執行一個語句 - Quit: 該線程正在退出 - Refresh:該線程正在刷表,日誌或緩存;或者在重置狀態變量,或者在複製服務器信息 - Register Slave: 正在註冊從節點 - Reset Stmt: 正在重置 prepared statement - Set Option: 正在設置或重置客戶端的 statement-execution 選項 - Shutdown: 正在關閉服務器 - Sleep: 正在等待客戶端向它發送執行語句 - Statistics: 該線程正在生成 server-status 信息 - Table Dump: 正在發送表的內容到從服務器
經常用到的查詢sql:
-- 按客戶端 IP 分組,看哪個客戶端的鏈接數最多 select client_ip,count(client_ip) as client_num from (select substring_index(host,':' ,1) as client_ip from processlist ) as connect_info group by client_ip order by client_num desc; -- 查看正在執行的線程,並按 Time 倒排序,看看有沒有執行時間特別長的線程 select * from information_schema.processlist where Command != 'Sleep' order by -- 找出所有執行時間超過 5 分鐘的線程,拼湊出 kill 語句,方便後面查殺 select concat('kill ', id, ';') from information_schema.processlist where Command != 'Sleep' and Time > 300 order by Time desc;