mysql not in优化_实践中如何优化MySQL(收藏)
- SQL語句的優化:
- 1、盡量避免使用子查詢
- 3、用IN來替換OR
- 4、LIKE前綴%號、雙百分號、_下劃線查詢非索引列或*無法使用到索引,如果查詢的是索引列則可以
- 5、讀取適當的記錄LIMIT M,N,而不要讀多余的記錄
- 6、避免數據類型不一致
- 7、分組統計可以禁止排序sort,總和查詢可以禁止排重用union all
- 8、避免隨機取記錄
- 9、禁止不必要的ORDER BY排序
- 10、批量INSERT插入
- 11、不要使用NOT等負向查詢條件
- 12、盡量不用select *
- 13、**區分in和exists**
- 索引的優化:
- 1、Join語句的優化
- 2、避免索引失效
在開始介紹如何優化sql前,先附上mysql內部邏輯圖讓大家有所了解
① SQL語句及索引的優化
SQL語句的優化:
1、盡量避免使用子查詢
2、避免函數索引
3、用IN來替換OR
另外,MySQL對于IN做了相應的優化,即將IN中的常量全部存儲在一個數組里面,而且這個數組是排好序的。但是如果數值較多,產生的消耗也是比較大的。再例如:select id from table_name where num in(1,2,3) 對于連續的數值,能用 between 就不要用 in 了;再或者使用連接來替換。
4、LIKE前綴%號、雙百分號、_下劃線查詢非索引列或*無法使用到索引,如果查詢的是索引列則可以
5、讀取適當的記錄LIMIT M,N,而不要讀多余的記錄
select id,name from table_name limit 866613, 20使用上述sql語句做分頁的時候,可能有人會發現,隨著表數據量的增加,直接使用limit分頁查詢會越來越慢。
優化的方法如下:可以取前一頁的最大行數的id,然后根據這個最大的id來限制下一頁的起點。比如此列中,上一頁最大的id是866612。sql可以采用如下的寫法:
select id,name from table_name where id> 866612 limit 206、避免數據類型不一致
7、分組統計可以禁止排序sort,總和查詢可以禁止排重用union all
union和union all的差異主要是前者需要將結果集合并后再進行唯一性過濾操作,這就會涉及到排序,增加大量的CPU運算,加大資源消耗及延遲。**當然,union all的前提條件是兩個結果集沒有重復數據。**所以一般是我們明確知道不會出現重復數據的時候才建議使用 union all 提高速度。
另外,如果排序字段沒有用到索引,就盡量少排序;
8、避免隨機取記錄
9、禁止不必要的ORDER BY排序
10、批量INSERT插入
11、不要使用NOT等負向查詢條件
你可以想象一下,對于一棵B+樹,根節點是40,如果你的條件是等于20,就去左面查,你的條件等于50,就去右面查,但是你的條件是不等于66,索引應該咋辦?還不是遍歷一遍才知道。
12、盡量不用select *
SELECT *增加很多不必要的消耗(cpu、io、內存、網絡帶寬);增加了使用覆蓋索引的可能性;當表結構發生改變時,前者也需要經常更新。所以要求直接在select后面接上字段名。
13、區分in和exists
select * from 表A where id in (select id from 表B)上面sql語句相當于
select * from 表A where exists(select * from 表B where 表B.id=表A.id)區分in和exists主要是造成了驅動順序的改變(這是性能變化的關鍵),如果是exists,那么以外層表為驅動表,先被訪問,如果是IN,那么先執行子查詢。所以IN適合于外表大而內表小的情況;EXISTS適合于外表小而內表大的情況。
索引的優化:
1、Join語句的優化
Join 性能點
當我們執行兩個表的Join的時候,就會有一個比較的過程,逐條比較兩個表的語句是比較慢的,因此可以把兩個表中數據依次讀進一個內存塊中,在Mysql中執行:show variables like 'join_buffer_size',可以看到join在內存中的緩存池大小,其大小將會影響join語句的性能。
在執行join的時候,數據庫會選擇一個表把他要返回以及需要進行和其他表進行比較的數據放進join_buffer。
如果是有索引的情況,則直接讀取兩個表的索引樹進行比較就可以了。
若沒有索引,則會使用 'Block nested loop' 算法,Block 塊,也就是說每次都會取一塊數據到內存以減少I/O的開銷
另外,Innodb會為每個數據表分配一個存儲在磁盤的 表名.ibd 文件,若關聯的表過多,將會導致查詢的時候磁盤的磁頭移動次數過多,從而影響性能
所以實踐中,盡可能減少Join語句中的NestedLoop的循環次數:“永遠用小結果集驅動大的結果集”
1、條件中盡量能夠過濾一些行將驅動表變得小一點,用小表去驅動大表
2、右表的條件列一定要加上索引(主鍵、唯一索引、前綴索引等),最好能夠使type達到range及以上(ref,eq_ref,const,system)
性能優化,left join 是由左邊決定的,左邊一定都有,所以右邊是我們的關鍵點,建立索引要建在右邊。當然如果索引是在左邊的,我們可以考慮使用右連接,如下
select * from atable left join btable on atable.aid=btable.bid;//最好在bid上建索引(Tips:Join左連接在右邊建立索引;組合索引則盡量將數據量大的放在左邊,在左邊建立索引)
2、避免索引失效
1.最佳左前綴法則
如果索引了多列,要遵守最左前綴法則,指的是查詢從索引的最左前列開始并且不跳過索引中的列。Mysql查詢優化器會對查詢的字段進行改進,判斷查詢的字段以哪種形式組合能使得查詢更快,所有比如創建的是(a,b)索引,查詢的是(b,a),查詢優化器會修改成(a,b)后使用索引查詢。
2.不在索引列上做任何操作
(計算、函數、(自動or手動)類型轉換),會導致索引失效而轉向全表掃描。
3.存儲引擎不能使用索引中范圍條件右邊的列。
如這樣的sql: select * from user where username='123' and age>20 and phone='1390012345',其中username, age, phone都有索引,只有username和age會生效,phone的索引沒有用到。
4.盡量使用覆蓋索引(只訪問索引的查詢(索引列和查詢列一致))
如select age from user減少`select *``
5.mysql在使用不等于(!= 或者 <>)的時候無法使用索引會導致全表掃描。
6.is null, is not null 也無法使用索引,在實際中盡量不要使用null。
7.like 以通配符開頭(‘%abc..’)mysql索引失效會變成全表掃描的操作。
所以最好用右邊like 'abc%'。如果兩邊都要用,可以用select age from user where username like '%abc%',其中age是必須是索引列,才可讓索引生效
假如index(a,b,c), where a=3 and b like 'abc%' and c=4,a能用,b能用,c不能用,類似于不能使用范圍條件右邊的列的索引
對于一棵B+樹來講,如果根是字符def,如果通配符在后面,例如abc%,則應該搜索左面,例如efg%,則應該搜索右面,如果通配符在前面%abc,則不知道應該走哪一面,還是都掃描一遍吧。
8.字符串不加單引號索引失效
9.少用or,用它來連接時會索引失效
10.盡量避免子查詢,而用join
11、在組合索引中,將有區分度的索引放在前面
如果沒有區分度,例如用性別,相當于把整個大表分成兩部分,查找數據還是需要遍歷半個表才能找到,使得索引失去了意義。
12、避免在 where 子句中對字段進行 null 值判斷
對于null的判斷會導致引擎放棄使用索引而進行全表掃描。
② 數據庫表結構的優化:使得數據庫結構符合三大范式與BCNF
③ 系統配置的優化
④ 硬件的優化
總結
以上是生活随笔為你收集整理的mysql not in优化_实践中如何优化MySQL(收藏)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: oracle erp 报表开发手册,处置
- 下一篇: linux cmake编译源码,linu