2014-03-06 74 views
0

我需要優化以下查詢需要幫助優化我的SQL查詢

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

請發佈'show create table stats_novercanet.mnp_prod_stat_promotion_traffic'的結果' – fancyPants

+0

如果您希望我們幫助優化查詢,您需要向我們顯示錶格和索引定義**以及每個行的計數的表格。也許你的表格定義不好。也許索引沒有正確創建。也許你沒有一個你認爲你做過的那個專欄的索引。沒有看到表和索引定義,我們不能說。我們還需要行計數,因爲這會大大影響查詢優化。如果你知道如何做一個'EXPLAIN'或者得到一個執行計劃,那就把結果也放在問題中。如果您沒有索引,請儘快訪問http://use-the-index-luke.com。 –

+0

我已經添加了show create table stats_novercanet.mnp_prod_stat_promotion_traffic的結果;有問題。解釋查詢的結果也存在問題本身。我忘了寫我需要加入mnp_prod_stat_customer_first_signup表中查詢中使用的全部結果條件。但是如果沒有選擇過濾條件不存在的地方。 – user1648204

回答

0

多少結果你期望得到恢復。如果您知道例如您只希望返回一條記錄,那麼您可以使用LIMITS

當運行查詢時,它將搜索整個表中的記錄,但是如果您知道只有一個,兩個或三個結果返回那麼你可以限制。這將節省MySQL大量的時間,但是它又取決於你正在執行的結果的數量,你將不得不將它應用到你正在運行的表上。

此外,另一個技巧是檢查您正在使用什麼類型的表類型。看看這個網頁的更多信息:http://www.mysqltutorial.org/understand-mysql-table-types-innodb-myisam.aspx

另一個選擇是建立一個腳本來使用上面的現有查詢並將結果存儲在一個新表中,並且每個月通過cron運行腳本一次像午夜。我爲一個分析項目做了這個,並且它運作良好。

+0

我想要那個月的所有結果。我不能使用限制。另外它使用的是MyISAM數據引擎 – user1648204

+0

我在關於使用腳本和表格的答案的底部添加了另一個建議。祝你好運! – Cameron

+0

謝謝Cameron我可能會使用腳本和表格,但是再次運行一天也會花費太長時間,每日腳本應該更新一個月,這樣腳本就會永遠運行起來。 – user1648204