【发布时间】:2015-09-27 11:23:17
【问题描述】:
目前我有一个架构如下的表:
mData | CREATE TABLE `mData` (
`m1` mediumint(8) unsigned DEFAULT NULL,
`m2` smallint(5) unsigned DEFAULT NULL,
`m3` bigint(20) DEFAULT NULL,
`m4` tinyint(4) DEFAULT NULL,
`m5` date DEFAULT NULL,
KEY `m_m1` (`m1`) USING HASH,
KEY `m_date` (`m5`),
KEY `m_m2` (`m2`),
KEY `m_combined` (`m1`,`m2`,`m5`),
KEY `m1_tradeday` (`m1`,`m5`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
/*!50100 PARTITION BY RANGE ( YEAR(m5))
SUBPARTITION BY HASH (MONTH(m5))
(PARTITION p2013 VALUES LESS THAN (2014)
(SUBPARTITION dec_2013 ENGINE = InnoDB,
SUBPARTITION jan_2013 ENGINE = InnoDB,
SUBPARTITION feb_2013 ENGINE = InnoDB,
SUBPARTITION mar_2013 ENGINE = InnoDB,
SUBPARTITION apr_2013 ENGINE = InnoDB,
SUBPARTITION may_2013 ENGINE = InnoDB,
SUBPARTITION jun_2013 ENGINE = InnoDB,
SUBPARTITION jul_2013 ENGINE = InnoDB,
SUBPARTITION aug_2013 ENGINE = InnoDB,
SUBPARTITION sep_2013 ENGINE = InnoDB,
SUBPARTITION oct_2013 ENGINE = InnoDB,
SUBPARTITION nov_2013 ENGINE = InnoDB),
PARTITION p2014 VALUES LESS THAN (2015)
(SUBPARTITION dec_2014 ENGINE = InnoDB,
SUBPARTITION jan_2014 ENGINE = InnoDB,
SUBPARTITION feb_2014 ENGINE = InnoDB,
SUBPARTITION mar_2014 ENGINE = InnoDB,
SUBPARTITION apr_2014 ENGINE = InnoDB,
SUBPARTITION may_2014 ENGINE = InnoDB,
SUBPARTITION jun_2014 ENGINE = InnoDB,
SUBPARTITION jul_2014 ENGINE = InnoDB,
SUBPARTITION aug_2014 ENGINE = InnoDB,
SUBPARTITION sep_2014 ENGINE = InnoDB,
SUBPARTITION oct_2014 ENGINE = InnoDB,
SUBPARTITION nov_2014 ENGINE = InnoDB),
PARTITION p2015 VALUES LESS THAN (2016)
(SUBPARTITION dec_2015 ENGINE = InnoDB,
SUBPARTITION jan_2015 ENGINE = InnoDB,
SUBPARTITION feb_2015 ENGINE = InnoDB,
SUBPARTITION mar_2015 ENGINE = InnoDB,
SUBPARTITION apr_2015 ENGINE = InnoDB,
SUBPARTITION may_2015 ENGINE = InnoDB,
SUBPARTITION jun_2015 ENGINE = InnoDB,
SUBPARTITION jul_2015 ENGINE = InnoDB,
SUBPARTITION aug_2015 ENGINE = InnoDB,
SUBPARTITION sep_2015 ENGINE = InnoDB,
SUBPARTITION oct_2015 ENGINE = InnoDB,
SUBPARTITION nov_2015 ENGINE = InnoDB),
PARTITION p2016 VALUES LESS THAN (2017)
(SUBPARTITION dec_2016 ENGINE = InnoDB,
SUBPARTITION jan_2016 ENGINE = InnoDB,
SUBPARTITION feb_2016 ENGINE = InnoDB,
SUBPARTITION mar_2016 ENGINE = InnoDB,
SUBPARTITION apr_2016 ENGINE = InnoDB,
SUBPARTITION may_2016 ENGINE = InnoDB,
SUBPARTITION jun_2016 ENGINE = InnoDB,
SUBPARTITION jul_2016 ENGINE = InnoDB,
SUBPARTITION aug_2016 ENGINE = InnoDB,
SUBPARTITION sep_2016 ENGINE = InnoDB,
SUBPARTITION oct_2016 ENGINE = InnoDB,
SUBPARTITION nov_2016 ENGINE = InnoDB),
PARTITION pmax VALUES LESS THAN MAXVALUE
(SUBPARTITION dec_max ENGINE = InnoDB,
SUBPARTITION jan_max ENGINE = InnoDB,
SUBPARTITION feb_max ENGINE = InnoDB,
SUBPARTITION mar_max ENGINE = InnoDB,
SUBPARTITION apr_max ENGINE = InnoDB,
SUBPARTITION may_max ENGINE = InnoDB,
SUBPARTITION jun_max ENGINE = InnoDB,
SUBPARTITION jul_max ENGINE = InnoDB,
SUBPARTITION aug_max ENGINE = InnoDB,
SUBPARTITION sep_max ENGINE = InnoDB,
SUBPARTITION oct_max ENGINE = InnoDB,
SUBPARTITION nov_max ENGINE = InnoDB)) */ |
m1、m2 和 m5 在此表中设置为索引,唯一/主要不适用于我的情况。
随着数据越来越大(每天 100,000 个新行),更新命令变得非常缓慢。
我想知道是否有任何方法可以改进以下语句。
update mData as a join (select * from mData
where m1 = 326 and m5 = '2015- 07-06' ) as b
on a.m5 > b.m5 and a.m1 = b.m1
and a.m2 = b.m2 and a.m3 = b.m3
set a.m4 = 0;
我很确定,在 select 语句中,如果我将 mData as a 替换为 (select * from mData where m1 = 326),执行时间可以大大减少(从 5 秒到不到 1 秒)。
但是,在UPDATE 语句中不能这样做。
有没有办法解决这个问题,加快更新速度?
附:该表已按月(m5)和年(m5)分区
这里是我的join查询的EXPLAIN分区,很乱,希望你不要介意。添加 ' 和 a.m5 > '2015-07-06' 确实提高了性能,查询时间从 0.68 秒下降到 0.2 秒。
explain partitions (select * from (select * from mData where m1 = 326) as a join (select * from mData where m1 = 326 and m5= '2015-07-06') as b on a.m5 > b.m5 and a.m1 = b.m1 and a.m2 = b.m2 and a.m3 = b.m3 and a.m5 > '2015-07-06');
|编号 |选择类型 |表|分区|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+--------------+------------+------ ------------------------------ -------------------- -------------------------------------------------- ---------- ---------------------------------------- ---------------------------------------- ---------- -------------------------------------------------- -------------------- ------------------ ---------------------- ---------------------------------------- ---------- -------------------------------------------------- -------- ------------------------------------------ -------------------------- ------------ -------------------------------------------------- -------------------------------------------------- ------------------------------------------------ -------------------------------------------------- ------------------------------ -------------------- -------------------------------------------------- ---------- ------------------+------+-- ---------------------------------------- --------+- -------------+---------+------+------+------------ -------------------- + | 1 |初级 | |空值 |全部 |空 |空 |空 |空 | 358 | | | 1 |初级 | |空值 |全部 |空 |空 |空 |空 | 1073 |使用哪里;使用连接缓冲区 | | 3 |派生 |数据 | p2015_jul_2015|参考 | m_m1,m_m5,m_combined,m1_m5 | m1_m5 | 8 | |第357章使用位置 | | 2 |派生 |数据 | p2013_dec_2013,p2013_jan_2013,p2013_feb_2013,P 2013_mar_2013,p2013_apr_2013,p2013_may_2013,p2013_jun_2013,p2013_jul_2013,p2013_ aug_2013,p2013_sep_2013,p2013_oct_2013,p2013_nov_2013,p2014_dec_2014,p2014_jan_2 014,p2014_feb_2014,p2014_mar_2014,p2014_apr_2014,p2014_may_2014,p2014_jun_2014,P 2014_jul_2014,p2014_aug_2014,p2014_sep_2014,p2014_oct_2014, p2014_nov_2014,p2015_ dec_2015,p2015_jan_2015,p2015_feb_2015,p2015_mar_2015,p2015_apr_2015,p2015_may_2 015,p2015_jun_2015,p2015_jul_2015,p2015_aug_2015,p2015_sep_2015,p2015_oct_2015,P 2015_nov_2015,p2016_dec_2016,p2016_jan_2016,p2016_feb_2016,p2016_mar_2016,p2016_ apr_2016,p2016_may_2016,p2016_jun_2016,p2016_jul_2016,p2016_aug_2016,p2016_sep_2 016,p2016_oct_2016,p2016_nov_2016,pmax_dec_max,pmax_jan_max,pmax_feb_max,pmax_mar_max,pmax_apr_max,pmax_may_max,pmax_jun_max,pmax_jul_max,pmax_aug_max,pmax_sep_max,pmax_oct_max,pmax_nov_max |参考 | m_m1,m_combined,m1_m5 | m_m1 | 4 | | 1074 |使用位置 |
以下是“Rick James”提出的查询说明
EXPLAIN PARTITIONS select * from ccass_data where sid = 326 and trade_day = '2015-07-06';
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+----------------+------+--------------------------------------------------+--------------+---------+-------------+------+-------------+
| 1 | SIMPLE | mData | p2015_jul_2015 | ref | m_m1,m_m5,m_combined,m1_m5 | m1_m5 | 8 | const,const | 357 | Using where |
【问题讨论】:
-
为什么不能在更新语句中添加
where m1 = 326?另外,m1,m2,m3上是否有复合索引? -
因为这并没有改善。它是一个完整的表和它的子查询之间的连接,它占据了大部分的执行时间。添加 where 没有区别。
-
对于复合索引,是不是会加快很多?非常感谢您的建议。
-
如果您在
m1,m2,m5上有一个复合索引,则连接目前正在使用它的前两个部分。如果所有 3 个都有索引,它应该会更快,但我无法预测会快多少。 -
我尝试了m1、m2和m5的复合索引,还是一样
标签: mysql sql performance sql-update large-data