说有两个表,如:
表campaign
:
+-------------------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+--------------+------+-----+-------------------+-----------------------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| campaign_id | varchar(64) | YES | UNI | NULL | |
| account_id | varchar(64) | YES | MUL | NULL | |
| name | blob | YES | | NULL | |
| objective | varchar(64) | YES | | NULL | |
| can_use_spend_cap | tinyint(2) | YES | | NULL | |
| status | varchar(64) | YES | | NULL | |
| spend_cap | bigint(14) | YES | | 0 | |
| effective_status | char(128) | YES | | NULL | |
| promoted_object | text | YES | | NULL | |
| lifetime_budget | bigint(14) | YES | | NULL | |
| daily_budget | bigint(14) | YES | | NULL | |
| update_time | timestamp | NO | | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| create_time | timestamp | NO | MUL | CURRENT_TIMESTAMP | |
| task_status | tinyint(3) | YES | | NULL | |
| is_smb | tinyint(3) | YES | | NULL | |
| rule_created | tinyint(4) | YES | | 0 | |
| access_token | varchar(255) | YES | MUL | NULL | |
+-------------------+--------------+------+-----+-------------------+-----------------------------+
表campaign_statistic
+---------------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| campaign_id | varchar(64) | YES | MUL | NULL | |
| account_id | varchar(64) | YES | | NULL | |
| impressions | int(11) | YES | | NULL | |
| clicks | int(11) | YES | | NULL | |
| spend | decimal(14,6) | YES | | NULL | |
| cpc | decimal(14,6) | YES | | NULL | |
| cpm | decimal(14,6) | YES | | NULL | |
| cpp | decimal(14,6) | YES | | NULL | |
| ctr | decimal(14,6) | YES | | NULL | |
| cost_per_purchase | decimal(14,6) | YES | | NULL | |
| cost_per_addtocart | decimal(14,6) | YES | | NULL | |
| fb_pixel_addtocart | int(11) | YES | | NULL | |
| fb_pixel_addtocart_values | decimal(14,6) | YES | | NULL | |
| fb_pixel_purchase | int(11) | YES | | NULL | |
| fb_pixel_purchase_values | decimal(14,6) | YES | | NULL | |
| roas | decimal(14,6) | YES | | NULL | |
| roi | decimal(14,6) | YES | | NULL | |
| dt | date | YES | | NULL | |
+---------------------------+---------------+------+-----+---------+----------------+
我想加入这两个表,然后进行order
,search
和time_range
的工作。
我尝试过这样的尝试:
EXPLAIN SELECT
campaign.id AS id,
campaign.campaign_id AS campaign_id,
campaign.account_id AS account_id,
campaign.daily_budget AS daily_budget,
campaign.lifetime_budget AS lifetime_budget,
campaign.name AS name,
campaign.effective_status AS effective_status,
campaign.daily_budget AS daily_budget,
statistic.spend AS spend,
statistic.clicks AS clicks,
statistic.impressions AS impressions,
statistic.spend AS spend,
statistic.fb_pixel_addtocart AS fb_pixel_addtocart,
statistic.fb_pixel_addtocart_values AS fb_pixel_addtocart_values,
statistic.fb_pixel_purchase AS fb_pixel_purchase,
statistic.fb_pixel_purchase_values AS fb_pixel_purchase_values,
statistic.cpc AS cpc,
statistic.ctr AS ctr,
statistic.cpm AS cpm,
statistic.cost_per_addtocart AS cost_per_addtocart,
statistic.cost_per_purchase AS cost_per_purchase,
statistic.roi AS roi,
statistic.roas AS roas,
campaign.rule_created AS rule_created,
campaign.is_smb AS is_smb
FROM `campaign` as campaign
LEFT JOIN
(SELECT
campaign_id,
SUM(impressions) AS impressions,
SUM(clicks) AS clicks,
ROUND(SUM(spend),2) AS spend,
SUM(fb_pixel_addtocart) AS fb_pixel_addtocart,
ROUND(SUM(fb_pixel_addtocart_values),2) AS fb_pixel_addtocart_values,
ROUND(SUM(fb_pixel_purchase),2) AS fb_pixel_purchase,
ROUND(SUM(fb_pixel_purchase_values),2) AS fb_pixel_purchase_values,
ROUND(SUM(clicks)*100/SUM(impressions), 6) AS ctr,
ROUND(SUM(spend)/SUM(clicks), 6) AS cpc,
ROUND(SUM(spend)*1000/SUM(impressions), 6) AS cpm,
ROUND(SUM( spend )/SUM(fb_pixel_addtocart), 6) AS cost_per_addtocart,
ROUND(SUM( spend )/SUM(fb_pixel_purchase), 6) AS cost_per_purchase,
ROUND(SUM( fb_pixel_purchase )/SUM(spend), 6) AS roi,
ROUND(SUM( fb_pixel_purchase )/SUM(spend), 6) AS roas
FROM `campaign_statistic` WHERE dt BETWEEN 2019-07-08 AND 2019-07-08 GROUP BY campaign_id) statistic
ON statistic.campaign_id = campaign.campaign_id
WHERE campaign.account_id = 1000623940119431
AND (campaign.campaign_id LIKE "%%" OR campaign.name LIKE "%%") ORDER BY id ASC
它可以工作,但是查询速度慢得多,很抱歉,我是mysql的新手。
如何优化sql并加快查询速度?
任何评论都非常受欢迎。非常感谢。
更新问题:
使用时,我会使用SUM
,ROUND
或其他函数来计算功。似乎
索引未使用,查询速度更低。为什么会这样?
1)
EXPLAIN
SELECT campaign_id
FROM `campaign_statistic`
WHERE dt >= '2019-03-01' AND dt <= '2019-03-31'
GROUP BY fb_campaign_id
+----+-------------+----------------------------+-------+--------------------+---------------+---------+------+--------+-----------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------------+-------+--------------------+---------------+---------+------+--------+-----------------------------------------------------------+
| 1 | SIMPLE | campaign_statistic | range | campaign_date,date | campaign_date | 4 | NULL | 567748 | Using where; Using index; Using temporary; Using filesort |
+----+-------------+----------------------------+-------+--------------------+---------------+---------+------+--------+-----------------------------------------------------------+
2)
EXPLAIN
SELECT campaign_id,
SUM(impressions) AS impressions
FROM `campaign_statistic`
WHERE dt >= '2019-03-01' AND dt <= '2019-03-31'
GROUP BY fb_campaign_id
+----+-------------+----------------------------+------+--------------------+------+---------+------+---------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------------+------+--------------------+------+---------+------+---------+----------------------------------------------+
| 1 | SIMPLE | campaign_statistic | ALL | campaign_date,date | NULL | NULL | NULL | 1647182 | Using where; Using temporary; Using filesort |
+----+-------------+----------------------------+------+--------------------+------+---------+------+---------+----------------------------------------------+
答案 0 :(得分:3)
首先,您的查询存在一些明显的缺陷。看起来应该像这样:
SELECT . . .
FROM `campaign` as campaign LEFT JOIN
(SELECT campaign_id,
SUM(impressions) AS impressions,
SUM(clicks) AS clicks,
ROUND(SUM(spend),2) AS spend,
SUM(fb_pixel_addtocart) AS fb_pixel_addtocart,
ROUND(SUM(fb_pixel_addtocart_values),2) AS fb_pixel_addtocart_values,
ROUND(SUM(fb_pixel_purchase),2) AS fb_pixel_purchase,
ROUND(SUM(fb_pixel_purchase_values),2) AS fb_pixel_purchase_values,
ROUND(SUM(clicks)*100/SUM(impressions), 6) AS ctr,
ROUND(SUM(spend)/SUM(clicks), 6) AS cpc,
ROUND(SUM(spend)*1000/SUM(impressions), 6) AS cpm,
ROUND(SUM( spend )/SUM(fb_pixel_addtocart), 6) AS cost_per_addtocart,
ROUND(SUM( spend )/SUM(fb_pixel_purchase), 6) AS cost_per_purchase,
ROUND(SUM( fb_pixel_purchase )/SUM(spend), 6) AS roi,
ROUND(SUM( fb_pixel_purchase )/SUM(spend), 6) AS roas
FROM `campaign_statistic`
WHERE dt BETWEEN '2019-07-08' AND '2019-07-08'
GROUP BY campaign_id
) statistic
ON statistic.campaign_id = campaign.campaign_id
WHERE campaign.account_id = 1000623940119431 AND
(campaign.campaign_id LIKE '%%' OR campaign.name LIKE '%%')
ORDER BY id ASC;
一个开始的地方是campaign(account_id, campaign_id, name)
上的索引。然后对于子查询,campaign_statistic(dt, campaign_id)
。
根据数据,可能会发现“展开”聚合更好。也就是说,先进行JOIN
,然后对两个表进行汇总。
答案 1 :(得分:0)
您可以避免聚合操作并在您的语言程序中进行吗?