浅析多个单列索引和联合索引的区别
1.創建表格
DROP TABLE IF EXISTS `t_mobilesms_11`; CREATE TABLE `t_mobilesms_11` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`userId` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '用戶id,創建任務時的userid',`mobile` varchar(24) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '手機號碼',`billMonth` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '賬單月',`time` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收/發短信時間',`peerNumber` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '對方號碼',`location` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '通信地(自己的)',`sendType` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'SEND-發送; RECEIVE-收取',`msgType` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'SMS-短信; MSS-彩信',`serviceName` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '業務名稱. e.g. 點對點(網內)',`fee` int(11) NULL DEFAULT NULL COMMENT '通信費(單位分)',`createTime` datetime(0) NULL DEFAULT NULL COMMENT '創建時間',`lastModifyTime` datetime(0) NULL DEFAULT NULL COMMENT '最后修改時間',PRIMARY KEY (`id`) USING BTREE,INDEX `聯合索引`(`userId`, `mobile`, `billMonth`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 71185 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '手機短信詳情' ROW_FORMAT = Dynamic;SET FOREIGN_KEY_CHECKS = 1;索引字段:userId,mobile,billMonth三個字段添加上聯合索引!
我們選擇explain查看執行計劃來查看索引利用情況
組合索引測試
1.查詢條件為userId
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222';
我們可以通過key看到,聯合索引有效
2.查詢條件為mobile
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE mobile='18300763618';3.查詢條件billMonth
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE billMonth='2018-04'4.查詢條件為userId and mobile
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' AND mobile='13281899972'5.查詢條件為mobile and userId
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE mobile='13281899972' AND userid='2222'6.查詢條件為userId or mobile
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' OR mobile='13281899972'7.查詢條件為 userid and billMonth
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' AND billMonth='2018-04'8.查詢條件為mobile and billMonth
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE mobile='13281899972' AND billMonth='2018-04'9.查詢條件為userId and mobile and billMonth
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' AND mobile='13281899972' AND billMonth='2018-04'10.查詢條件為userId and mobile or billMonth
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' AND mobile='13281899972' OR billMonth='2018-04';
11.查詢條件為userId or mobile and billMonth
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' OR mobile='13281899972' AND billMonth='2018-04';總結:聯合索引的最左原則
失效條件
- like 以%開頭,索引無效;當like前綴沒有%,后綴有%時,索引有效。
- 查詢條件中有or
- where條件索引字段有運算或者函數的
- 如果列類型是字符串,那一定要在條件中將數據使用引號引用起來,否則不使用索引
- 左連接查詢或者右連接查詢查詢關聯的字段編碼格式不一樣
- 如果mysql估計使用全表掃描要比使用索引快,則不使用索引
-
連接查詢中,按照優化器順序的第一張表不會走索引
-
如果查詢中沒有用到聯合索引的第一個字段,則不會走索引
單列索引測試
添加單列索引
SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0;-- ---------------------------- -- Table structure for t_mobilesms_11 -- ---------------------------- DROP TABLE IF EXISTS `t_mobilesms_11`; CREATE TABLE `t_mobilesms_11` (`id` bigint(20) NOT NULL AUTO_INCREMENT,`userId` varchar(255) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL DEFAULT '' COMMENT '用戶id,創建任務時的userid',`mobile` varchar(24) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '手機號碼',`billMonth` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '賬單月',`time` varchar(32) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '收/發短信時間',`peerNumber` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '對方號碼',`location` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '通信地(自己的)',`sendType` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'SEND-發送; RECEIVE-收取',`msgType` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'SMS-短信; MSS-彩信',`serviceName` varchar(256) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '業務名稱. e.g. 點對點(網內)',`fee` int(11) NULL DEFAULT NULL COMMENT '通信費(單位分)',`createTime` datetime(0) NULL DEFAULT NULL COMMENT '創建時間',`lastModifyTime` datetime(0) NULL DEFAULT NULL COMMENT '最后修改時間',PRIMARY KEY (`id`) USING BTREE,INDEX `zdy_userid`(`userId`) USING BTREE,INDEX `zdy_mobile`(`mobile`) USING BTREE,INDEX `zdy_billMonth`(`billMonth`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 71185 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '手機短信詳情' ROW_FORMAT = Dynamic;-- ---------------------------- -- Records of t_mobilesms_111.查詢條件為 userId and mobile and billMonth
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' AND mobile='13281899972' AND billMonth='2018-04';2.查詢條件為mobile and billMonth
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE mobile='13281899972' AND billMonth='2018-04';3.查詢條件為userId or mobile
EXPLAIN SELECT * FROM `t_mobilesms_11` WHERE userid='2222' OR mobile='13281899972';
最終總結
利用索引中的附加列,您可以縮小搜索的范圍,但使用一個具有兩列的索引 不同于使用兩個單獨的索引。復合索引的結構與電話簿類似,人名由姓和名構成,電話簿首先按姓氏對進行排序,然后按名字對有相同姓氏的人進行排序。如果您知道姓,電話簿將非常有用;如果您知道姓和名,電話簿則更為有用,但如果您只知道名不姓,電話簿將沒有用處。
?
多個單列索引在多條件查詢時優化器會選擇最優索引策略,可能只用一個索引,也可能將多個索引全用上!?但多個單列索引底層會建立多個B+索引樹,比較占用空間,也會浪費一定搜索效率,故如果只有多條件聯合查詢時最好建聯合索引!
最左前綴原則:
顧名思義是最左優先,以最左邊的為起點任何連續的索引都能匹配上,
注:如果第一個字段是范圍查詢需要單獨建一個索引
注:在創建聯合索引時,要根據業務需求,where子句中使用最頻繁的一列放在最左邊。這樣的話擴展性較好,比如 userid 經常需要作為查詢條件,而 mobile 不常常用,則需要把 userid 放在聯合索引的第一位置,即最左邊
同時存在聯合索引和單列索引(字段有重復的),這個時候查詢mysql會怎么用索引呢?
這個涉及到mysql本身的查詢優化器策略了,當一個表有多條索引可走時, Mysql 根據查詢語句的成本來選擇走哪條索引;
有人說where查詢是按照從左到右的順序,所以篩選力度大的條件盡量放前面。網上百度過,很多都是這種說法,但是據我研究,mysql執行優化器會對其進行優化,當不考慮索引時,where條件順序對效率沒有影響,真正有影響的是是否用到了索引!
聯合索引本質:
當創建**(a,b,c)聯合索引時,相當于創建了(a)單列索引**,(a,b)聯合索引以及**(a,b,c)聯合索引**
想要索引生效的話,只能使用 a和a,b和a,b,c三種組合;當然,我們上面測試過,a,c組合也可以,但實際上只用到了a的索引,c并沒有用到!
注:這個可以結合上邊的 通俗理解 來思考!
其他知識點:
1、需要加索引的字段,要在where條件中
2、數據量少的字段不需要加索引;因為建索引有一定開銷,如果數據量小則沒必要建索引(速度反而慢)
3、避免在where子句中使用or來連接條件,因為如果倆個字段中有一個沒有索引的話,引擎會放棄索引而產生全表掃描
4、聯合索引比對每個列分別建索引更有優勢,因為索引建立得越多就越占磁盤空間,在更新數據的時候速度會更慢。另外建立多列索引時,順序也是需要注意的,應該將嚴格的索引放在前面,這樣篩選的力度會更大,效率更高
總結
以上是生活随笔為你收集整理的浅析多个单列索引和联合索引的区别的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux最大文件句柄数量总结
- 下一篇: redis所有版本下载地址