mysql> show variables like 'query_cache%'; mysql> set global query_cache_type=1; mysql> set global query_cache_size=1024*1024*32
注意:mysql
select goods_id,cat_id,goods_name from good where cat_id in(select cat_id form category where parent_id=6); 這條語句執行會很是慢,由於它會掃描goods全表,逐行與category表對照 緣由:mysql的查詢優化器,針對in型作了優化,優化成了exists的執行效果。 改進:用鏈接查詢代替子查詢 select goods_id,g.cat_id,g.goods_name from goods as g inner join (select cat_id from category where parent_id=6) as t;
內層 from 語句查到的臨時表,沒有索引,因此from返回的內容要儘可能少算法
沒有查詢條件時count(*)很是快,不須要查表。但當有查詢條件時,速度將減慢。
可使用縮小範圍的方法優化查詢。
eg.sql
須要統計good_id>100的總數時通常會寫爲: select count(*) form goods where good_id>100; 優化爲: slect (select count(*) from goods)-(select count(*) from goods where id<100); 這樣,就把範圍由無限大縮小到了100
默認狀況下,MySQL 對全部 group by col1, col2, …… 的字段進行排序。這與查詢中指定 order by col1,col2,…… 相似。所以,若是顯示包括一個包含相同列的 order by 子句,則對 MySQL 的實際執行性能沒有什麼影響。 數據庫
若是查詢包括 group by 但用戶想要避免排序結果的消耗,則能夠指定 order by null 禁止排序。緩存
select col1 from table group by col2 order by null;
union all 不過濾 效率提升,如非必須,請用union all
由於 union去重的代價很是高, 放在程序裏去重.服務器
limit offset,n 當offset很是大時,效率極低。mysql並非跳過offset行,而後單取n行,而是取offset+n行,返回放棄前offset行,返回n行。
優化:性能
在一些sql請求中,mysql會建立臨時表,可能建立到內存中,也可能由內存中轉存到磁盤。
會建立臨時表的查詢:優化
若是是空的 myisam 表,默認就是先導入數據才建立索引的,不存在優化問題。
對於非空的 myisam 表,在一次性插入大量數據時,能夠經過設置 disable keys 和 enable keys 來提升導入的效率。線程
# 假設給 test 表一次性插入大量數據 alert table test disable keys; loading the data …… alert table test enable keys;
disable keys 的方式適用於 myisam 引擎,但不適用於 innodb 引擎。指針
使用多個值表的 insert 語句,能夠減小客戶端與數據庫之間的鏈接、關閉等資源消耗
insert into test values (1,1),(2,2),(3,3)……
delayed 的含義是讓 insert 語句立刻執行,其實數據都被放在內存的隊列中,並無真正的寫入磁盤,這比每條土局分別插入要快的多;
low_priority 恰好相反,在全部其餘用戶對錶的讀寫完成後才進行插入(好比記錄日誌的場景)
儘可能減小額外的排序,經過索引直接返回有序數據。
where 條件和 order_by 使用相同的索引,而且 order_by 的順序和索引的順序相同,而且 order by 的字段都是升序或者降序。不然確定須要額外的排序操做,這樣就會出現 filesort 。
在某些不得不使用 filesort 的場景中,須要想辦法加快 filesort 的操做。對於 filesort ,MySQL 有兩種排序算法。
首先根據條件取出排序字段和行指針信息,以後在排序區 sort_buffer 中排序。若是排序區 sort buffer 不夠,則在臨時表 temporary table 彙總存儲排序結果,完成排序後根據行指針回表讀取記錄。這種算法須要兩次訪問數據,第一次獲取排序字段和行指針信息,第二次根據行指針獲取記錄,尤爲是第二次讀取操做可能致使大量隨機 I/O 操做;優勢是排序的時候內存開銷較少
。
一次性取出知足條件的行的全部字段,而後在排序區 sort buffer 中排序後直接輸出結果集,排序的時候內存開銷較大,可是排序效率比兩次掃描算法要高。
mysql 經過比較系統變量 max_length_for_sort_data 的大小和 query 語句取出的字段總大小來判斷使用哪一種排序算法。若是 max_length_for_sort_data 更大,那麼使用第二種優化以後的算法,不然使用第一種算法。
適當加大系統變量 max_length_for_sort_data 的值,可以讓 MySQL 選擇更優化的 filesort 的排序算法,固然,設置過大,會形成cpu利用率太低和磁盤 I/O 太高
適當加大 sort_buffer_size 排序區,儘可能讓排序在內存中完成,而不是經過建立臨時表放在文件中進行;固然也不能不限制加大 sort_buffer_size 排序區,由於 sort_buffer_size 參數時每一個線程獨佔的,因此要考慮數據庫活動鏈接數和服務器內存的大小來適當設置排序區。
儘可能只使用必要的字段,select 具體的字段名稱,而不是 select * 選擇全部字段,這樣能夠減小排序區使用,提升 sql 性能。
sql 提示(sql hint) 是優化數據庫的一個重要手段,簡單來講就是在 sql 語句中加入一些人爲的提示來達到優化操做的目的。
select sql_buffer_results * from ……
這個語句將強制 MySQL 生成一個臨時結果集。只要臨時結果集生成後,全部表上的鎖定均被釋放。 這能再遇到表鎖定問題時或要花很長時間將結果傳給客戶端時有所幫助,由於能夠儘快釋放鎖資源。
經常使用的 sql 提示: