MySQL是當(dāng)今互聯(lián)網(wǎng)應(yīng)用最廣泛的數(shù)據(jù)庫(kù)之一,大部分互聯(lián)網(wǎng)公司都在使用MySQL作為其主要的數(shù)據(jù)庫(kù)系統(tǒng)。隨著業(yè)務(wù)數(shù)據(jù)不斷增加,MySQL分表成為了優(yōu)化性能的一種主流方式。然而,很多人在使用分表后,發(fā)現(xiàn)分表后的查詢效率卻比單表查詢效率低了很多,那這到底是為什么呢?
首先,我們需要了解分表的原理。分表就是將一張大表按照一定的規(guī)則拆分成多張小表,例如按照時(shí)間或者按照數(shù)據(jù)類別等等。這樣可以減小單張表的數(shù)據(jù)量,提高查詢速度。
--創(chuàng)建一張users表 CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶ID', `name` varchar(255) NOT NULL COMMENT '姓名', `age` int(11) NOT NULL COMMENT '年齡', `sex` varchar(2) NOT NULL COMMENT '性別', `phone` varchar(20) DEFAULT NULL COMMENT '聯(lián)系電話', `email` varchar(255) DEFAULT NULL COMMENT '郵箱', `create_time` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用戶表'; --創(chuàng)建按照年份拆分的表 CREATE TABLE `users_2018` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用戶ID', `name` varchar(255) NOT NULL COMMENT '姓名', `age` int(11) NOT NULL COMMENT '年齡', `sex` varchar(2) NOT NULL COMMENT '性別', `phone` varchar(20) DEFAULT NULL COMMENT '聯(lián)系電話', `email` varchar(255) DEFAULT NULL COMMENT '郵箱', `create_time` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='2018年用戶表';
其次,分表可能會(huì)導(dǎo)致跨表查詢。例如,我們需要查詢2018年的用戶數(shù)量:
SELECT COUNT(*) FROM `users_2018`;
但是,如果我們需要查詢2018年全年的用戶總數(shù),需要鏈接所有的分表進(jìn)行查詢:
SELECT SUM(num) FROM ( SELECT COUNT(*) AS num FROM `users_2018` UNION ALL SELECT COUNT(*) AS num FROM `users_2017` UNION ALL SELECT COUNT(*) AS num FROM `users_2016` UNION ALL ... ) AS t;
這樣的查詢會(huì)消耗更多的時(shí)間和資源,導(dǎo)致性能下降。
最后,分表還可能會(huì)影響索引的使用。例如,我們按照年份分表后,原本在主表上的索引并不能滿足跨表查詢的需要,需要重新在每個(gè)小表上增加索引,這會(huì)增加寫操作的時(shí)間。
綜上,分表的實(shí)現(xiàn)需要謹(jǐn)慎,需要綜合考慮數(shù)據(jù)量、查詢頻次、查詢方式、索引使用和跨表查詢等多個(gè)因素。否則,分表反而會(huì)導(dǎo)致查詢效率降低。