|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
正如前文所提到的,MySQL易学、易部署、易管理和易维护。我们的项目中有很多多少不即是的情形。明天写这篇文章复杂的剖析一下怎样个优化法。
这里的分表逻辑是依据t_group表的user_name组的个数来分的。
由于这类情形独自user_name字段上的索引就属于烂索引。起不了啥名分明的效果。
1、实验PROCEDURE.
DELIMITER$$
DROPPROCEDURE`t_girl`.`sp_split_table`$$
CREATEPROCEDURE`t_girl`.`sp_split_table`()
BEGIN
declaredoneintdefault0;
declarev_user_namevarchar(20)default;
declarev_table_namevarchar(64)default;
--Getallusersname.
declarecur1cursorforselectuser_namefromt_groupgroupbyuser_name;
--Dealwitherrororwarnings.
declarecontinuehandlerfor1329setdone=1;
--Opencursor.
opencur1;
whiledone1
do
fetchcur1intov_user_name;
ifnotdonethen
--Gettablename.
setv_table_name=concat(t_group_,v_user_name);
--Createnewextratable.
set@stmt=concat(createtable,v_table_name,liket_group);
prepares1from@stmt;
executes1;
dropprepares1;
--Loaddataintoit.
set@stmt=concat(insertinto,v_table_name,select*fromt_groupwhereuser_name=,v_user_name,);
prepares1from@stmt;
executes1;
dropprepares1;
endif;
endwhile;
--Closecursor.
closecur1;
--Freevariablefrommemory.
set@stmt=NULL;
END$$
DELIMITER;
2、实验表。
我们用一个有一万万笔记录的表来做测试。
MySQL>selectcount(*)fromt_group;
+----------+
|count(*)|
+----------+
|10388608|
+----------+
1rowinset(0.00sec)
表布局。
mysql>desct_group;
+-------------+------------------+------+-----+-------------------+----------------+
|Field|Type|Null|Key|Default|Extra|
+-------------+------------------+------+-----+-------------------+----------------+
|id|int(10)unsigned|NO|PRI|NULL|auto_increment|
|money|decimal(10,2)|NO||||
|user_name|varchar(20)|NO|MUL|||
|create_time|timestamp|NO||CURRENT_TIMESTAMP||
+-------------+------------------+------+-----+-------------------+----------------+
4rowsinset(0.00sec)
索引情形。
mysql>showindexfromt_group;
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
|Table|Non_unique|Key_name|Seq_in_index|Column_name|Collation|Cardinality|Sub_part|Packed|Null|Index_type|Comment|
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
|t_group|0|PRIMARY|1|id|A|10388608|NULL|NULL||BTREE||
|t_group|1|idx_user_name|1|user_name|A|8|NULL|NULL||BTREE||
|t_group|1|idx_combination1|1|user_name|A|8|NULL|NULL||BTREE||
|t_group|1|idx_combination1|2|money|A|3776|NULL|NULL||BTREE||
+---------+------------+------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
4rowsinset(0.00sec)
PS:
idx_combination1这个索引是必需的,由于要对user_name来GROUPBY。此时属于松懈索引扫描!固然完了后你能够干失落她。
idx_user_name这个索引是为了加速独自实行constant这类范例的查询。
我们要依据用户名来分表。
mysql>selectuser_namefromt_groupwhere1groupbyuser_name;
+-----------+
|user_name|
+-----------+
|david|
|leo|
|livia|
|lucy|
|sarah|
|simon|
|sony|
|sunny|
+-----------+
8rowsinset(0.00sec)
以是了局表应当是如许的。
mysql>showtablesliket_group_%;
+------------------------------+
|Tables_in_t_girl(t_group_%)|
+------------------------------+
|t_group_david|
|t_group_leo|
|t_group_livia|
|t_group_lucy|
|t_group_sarah|
|t_group_simon|
|t_group_sony|
|t_group_sunny|
+------------------------------+
8rowsinset(0.00sec)
3、对照了局。
mysql>selectcount(*)fromt_groupwhereuser_name=david;
+----------+
|count(*)|
+----------+
|1298576|
+----------+
1rowinset(1.71sec)
实行了快要2秒。
mysql>selectcount(*)fromt_group_david;
+----------+
|count(*)|
+----------+
|1298576|
+----------+
1rowinset(0.00sec)
几近是刹时的。
mysql>selectcount(*)fromt_groupwhereuser_namedavid;
+----------+
|count(*)|
+----------+
|9090032|
+----------+
1rowinset(9.26sec)
实行了快要10秒,能够设想,这个是实践的项目中是不克不及忍耐的。
mysql>select(selectcount(*)fromt_group)-(selectcount(*)fromt_group_david)astotal;
+---------+
|total|
+---------+
|9090032|
+---------+
1rowinset(0.00sec)
几近是刹时的。
我们来看看会萃函数。
关于原表的操纵。
mysql>selectmin(money),max(money)fromt_groupwhereuser_name=david;
+------------+------------+
|min(money)|max(money)|
+------------+------------+
|-6.41|500.59|
+------------+------------+
1rowinset(0.00sec)
最小,最年夜值都是FULLINDEXSCAN。以是是刹时的。
mysql>selectsum(money),avg(money)fromt_groupwhereuser_name=david;
+--------------+------------+
|sum(money)|avg(money)|
+--------------+------------+
|319992383.84|246.417910|
+--------------+------------+
1rowinset(2.15sec)
其他会萃函数的了局就不是FULLINDEXSCAN了。耗时2.15秒。
关于小表的操纵。
mysql>selectmin(money),max(money)fromt_group_david;
+------------+------------+
|min(money)|max(money)|
+------------+------------+
|-6.41|500.59|
+------------+------------+
1rowinset(1.50sec)
最年夜最小值完整是FULLTABLESCAN,耗时1.50秒,不划算。以此看来。
mysql>selectsum(money),avg(money)fromt_group_david;
+--------------+------------+
|sum(money)|avg(money)|
+--------------+------------+
|319992383.84|246.417910|
+--------------+------------+
1rowinset(1.68sec)
获得这两个了局也是花了快2秒,快了一点。
我们来看看这个小表的布局。
mysql>desct_group_david;
+-------------+------------------+------+-----+-------------------+----------------+
|Field|Type|Null|Key|Default|Extra|
+-------------+------------------+------+-----+-------------------+----------------+
|id|int(10)unsigned|NO|PRI|NULL|auto_increment|
|money|decimal(10,2)|NO||||
|user_name|varchar(20)|NO|MUL|||
|create_time|timestamp|NO||CURRENT_TIMESTAMP||
+-------------+------------------+------+-----+-------------------+----------------+
4rowsinset(0.00sec)
分明的user_name属性是过剩的。那末就干失落它。
mysql>altertablet_group_daviddropuser_name;
QueryOK,1298576rowsaffected(7.58sec)
Records:1298576Duplicates:0Warnings:0
如今来从头对小表运转查询
mysql>selectmin(money),max(money)fromt_group_david;
+------------+------------+
|min(money)|max(money)|
+------------+------------+
|-6.41|500.59|
+------------+------------+
1rowinset(0.00sec)
此时是刹时的。
mysql>selectsum(money),avg(money)fromt_group_david;
+--------------+------------+
|sum(money)|avg(money)|
+--------------+------------+
|319992383.84|246.417910|
+--------------+------------+
1rowinset(0.94sec)
此次算是把持在一秒之内了。
mysql>Aborted
小总结一下:分出的小表的属性只管越少越好。勇敢的往干吧。
曾经的功能列表可能会迅速变得过时了。而且,有些功能对有的应用程序非常重要,但是对别的应用程序则不一定。 |
|