我需要有关优化以下查询的帮助
select
DATE_FORMAT( traffic.stat_date, '%Y/%m'),
pt.promotion,
sum(traffic.voice_nat_onnet_mins - pt.promo_minutes_onnet) as total_onnet_mins,
sum(traffic.voice_nat_offnet_mins + traffic.voice_nat_landline_mins + traffic.voice_int_mins + traffic.voice_nng_mins + traffic.voice_not_rec_mins - pt.promo_minutes_offnet) as total_offnet_mins,
sum(traffic.sms_ptp_onnet_evts) as total_onnet_sms,
sum(traffic.sms_ptp_offnet_evts + traffic.sms_vas_pta_evts) as total_offnet_sms,
sum(traffic.dati_kb) as internet_kb
from
stats_novercanet.mnp_prod_stat_outgoing_traffic traffic
INNER JOIN stats_novercanet.mnp_prod_stat_promotion_traffic pt
ON pt.id_source_user=traffic.id_source_user
INNER JOIN stats_novercanet.mnp_prod_stat_customer_first_signup fs
ON pt.id_source_user = fs.id_source_user
where
traffic.stat_date between '2013-11-01' and '2013-11-30'
and traffic.stat_date >= (
select min(ft.stat_date)
from stats_novercanet.mnp_prod_stat_promotion_traffic ft
where
traffic.id_source_user=ft.id_source_user
and (ft.sub_rev>0 or ft.ren_rev>0)
and pt.promotion=ft.promotion
)
and pt.stat_date between '2013-11-01' and '2013-11-30'
group by
DATE_FORMAT( traffic.stat_date, '%Y/%m'),
pt.promotion
order by
DATE_FORMAT( traffic.stat_date, '%Y/%m'),
pt.promotion **
我已经使用了这个查询的解释,它向我展示了以下结果
+----+--------------------+---------+-------+------------------------------------------------+---------------------------------+---------+-----------------------------------------+--------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+---------+-------+------------------------------------------------+---------------------------------+---------+-----------------------------------------+--------+----------------------------------------------+
| 1 | PRIMARY | pt | range | idx_prod_stat_pro_tra_stat_date,id_source_user | idx_prod_stat_pro_tra_stat_date | 4 | NULL | 530114 | Using where; Using temporary; Using filesort |
| 1 | PRIMARY | fs | ref | id_source_user | id_source_user | 5 | stats_novercanet.pt.id_source_user | 1 | Using where; Using index |
| 1 | PRIMARY | traffic | ref | stat_date,id_source_user | id_source_user | 5 | stats_novercanet.pt.id_source_user | 60 | Using where |
| 2 | DEPENDENT SUBQUERY | ft | ref | id_source_user,promotion | id_source_user | 5 | stats_novercanet.traffic.id_source_user | 93 | Using where |
+----+--------------------+---------+-------+------------------------------------------------+---------------------------------+---------+-----------------------------------------+--------+----------------------------------------------+
任何有关优化的帮助都会很棒。我已经在id_source_user,stat_date和promotion上创建了索引,但没有运气。还尝试使用子查询加入,但没有运气。
结果如下:mnp_prod_stat_promotion_traffic。 * *
| mnp_prod_stat_promotion_traffic | CREATE TABLE `mnp_prod_stat_promotion_traffic` (
`stat_date` date DEFAULT NULL,
`id_source_user` int(64) DEFAULT NULL,
`promotion` varchar(64) DEFAULT NULL,
`num_of_sub` int(64) DEFAULT NULL,
`num_of_ren` int(64) DEFAULT NULL,
`credit` float DEFAULT NULL,
`minutes` float DEFAULT NULL,
`kb` float DEFAULT NULL,
`sms` int(64) DEFAULT NULL,
`lbs` int(64) DEFAULT NULL,
`sub_rev` float DEFAULT NULL,
`ren_rev` float DEFAULT NULL,
`consumed_credit` float DEFAULT NULL,
`sim_type` varchar(32) DEFAULT NULL,
`price_plan` varchar(64) DEFAULT NULL,
`WiFi_mins` float DEFAULT NULL,
`over_min` float DEFAULT NULL,
`over_min_consumed` float DEFAULT NULL,
`over_sms` float DEFAULT NULL,
`over_sms_consumed` float DEFAULT NULL,
`over_data` float DEFAULT NULL,
`over_data_consumed` float DEFAULT NULL,
`promo_minutes_onnet` float DEFAULT NULL,
`promo_minutes_offnet` float DEFAULT NULL,
`promo_sms_onnet` int(64) DEFAULT NULL,
`promo_sms_offnet` int(64) DEFAULT NULL,
KEY `idx_prod_stat_pro_tra_stat_date` (`stat_date`),
KEY `id_source_user` (`id_source_user`),
KEY `promotion` (`promotion`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
答案 0 :(得分:0)
您希望返回多少结果。如果您知道例如您只想要返回一条记录,那么您可以使用LIMITS
当查询运行时,它将在整个表中搜索该记录,但如果您知道只返回了一个,两个或三个结果,那么您可以使用LIMIT。这将为MySQL节省大量时间,但同样取决于您所使用的结果数量,并且您必须将其应用于您运行它的表。
另外,另一个提示是检查您正在使用的表类型。有关详细信息,请查看此网页:http://www.mysqltutorial.org/understand-mysql-table-types-innodb-myisam.aspx
另一个选项是构建一个脚本以使用上面的现有查询并将结果存储在一个新表中,并且每月只通过cron运行一次脚本,就像午夜一样。我这样做是为了一个分析项目,它运作良好。