我有很大的SQL查询:
SELECT
partner_id,
the_date,
SUM(clicks) as clicks,
SUM(total_count) as total_count,
SUM(count) as count,
SUM(total_sum) as total_sum,
SUM(received_sum) as received_sum,
SUM(partner_fee) as partner_fee
FROM (
SELECT
clicks.partner_id,
clicks.click_date as the_date,
clicks,
orders.total_count,
orders.count,
orders.total_sum,
orders.received_sum,
orders.partner_fee
FROM
(SELECT
partner_id, click_date, sum(clicks) as clicks
FROM
daily_metric WHERE DATE(click_date) BETWEEN '2013-04-01' AND '2013-04-30'
GROUP BY partner_id , click_date) as clicks
LEFT JOIN
(SELECT
partner_id,
DATE(order_date) as order_dates,
SUM(order_sum) as total_sum,
SUM(customer_paid_sum) as received_sum,
SUM(partner_fee) as partner_fee,
count(*) as total_count,
count(CASE
WHEN status = 1 THEN 1
ELSE NULL
END) as count
FROM
transaction WHERE DATE(order_date) BETWEEN '2013-04-01' AND '2013-04-30'
GROUP BY DATE(order_date) , partner_id) as orders ON orders.partner_id = clicks.partner_id AND clicks.click_date = orders.order_dates
UNION ALL SELECT
orders.partner_id,
orders.order_dates as the_date,
clicks,
orders.total_count,
orders.count,
orders.total_sum,
orders.received_sum,
orders.partner_fee
FROM
(SELECT
partner_id, click_date, sum(clicks) as clicks
FROM
daily_metric WHERE DATE(click_date) BETWEEN '2013-04-01' AND '2013-04-30'
GROUP BY partner_id , click_date) as clicks
RIGHT JOIN
(SELECT
partner_id,
DATE(order_date) as order_dates,
SUM(order_sum) as total_sum,
SUM(customer_paid_sum) as received_sum,
SUM(partner_fee) as partner_fee,
count(*) as total_count,
count(CASE
WHEN status = 1 THEN 1
ELSE NULL
END) as count
FROM
transaction WHERE DATE(order_date) BETWEEN '2013-04-01' AND '2013-04-30'
GROUP BY DATE(order_date) , partner_id) as orders ON orders.partner_id = clicks.partner_id AND clicks.click_date = orders.order_dates
WHERE
clicks.partner_id is NULL
ORDER BY the_date DESC
) as t
GROUP BY the_date ORDER BY the_date DESC LIMIT 50 OFFSET 0
这是我的疑问的解释:
+----+--------------+--------------+--------+---------------+---------+---------+------+---------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+--------------+--------+---------------+---------+---------+------+---------+----------------------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 162 | Using temporary; Using filesort |
| 2 | DERIVED | NULL | NULL | NULL | NULL | NULL | NULL | NULL | no matching row in const table |
| 4 | DERIVED | transaction | ALL | NULL | NULL | NULL | NULL | 280118 | Using where; Using temporary; Using filesort |
| 3 | DERIVED | daily_metric | index | NULL | PRIMARY | 1541 | NULL | 9370157 | Using where |
| 5 | UNION | <derived6> | system | NULL | NULL | NULL | NULL | 0 | const row not found |
| 5 | UNION | <derived7> | ALL | NULL | NULL | NULL | NULL | 162 | |
| 7 | DERIVED | transaction | ALL | NULL | NULL | NULL | NULL | 280118 | Using where; Using temporary; Using filesort |
| 6 | DERIVED | daily_metric | index | NULL | PRIMARY | 1541 | NULL | 9370157 | Using where |
| NULL | UNION RESULT | <union2,5> | ALL | NULL | NULL | NULL | NULL | NULL | Using filesort |
+----+--------------+--------------+--------+---------------+---------+---------+------+---------+----------------------------------------------+
9 rows in set (12.92 sec)
我需要任何建议如何将此查询优化为&gt; 5s
表索引:
mysql> show index from transaction
-> ;
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| transaction | 0 | PRIMARY | 1 | id | A | 279478 | NULL | NULL | | BTREE | | |
| transaction | 1 | partner_id | 1 | partner_id | A | 17 | NULL | NULL | | BTREE | | |
| transaction | 1 | updated_at | 1 | updated_at | A | 495 | NULL | NULL | YES | BTREE | | |
+-------------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.01 sec)
mysql> show index from daily_metric;
+--------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+--------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| daily_metric | 0 | PRIMARY | 1 | partner_id | A | 19 | NULL | NULL | | BTREE | | |
| daily_metric | 0 | PRIMARY | 2 | click_date | A | 10776 | NULL | NULL | | BTREE | | |
| daily_metric | 0 | PRIMARY | 3 | utm_content | A | 700476 | NULL | NULL | | BTREE | | |
| daily_metric | 0 | PRIMARY | 4 | utm_term | A | 9806670 | NULL | NULL | | BTREE | | |
| daily_metric | 1 | partner_id_index | 1 | partner_id | A | 19 | NULL | NULL | | BTREE | | |
| daily_metric | 1 | utm_content_index | 1 | utm_content | A | 891515 | NULL | NULL | | BTREE | | |
| daily_metric | 1 | utm_term_index | 1 | utm_term | A | 9806670 | NULL | NULL | | BTREE | | |
+--------------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
7 rows in set (0.03 sec)
表daily_metric
有大约10毫升的记录。
答案 0 :(得分:2)
您需要将其分解为所有子查询,并找出花费最多时间的位置。然后你可以看到一个索引是否会有所帮助。尝试自己计算子查询的时间。
我看到的一件事......你在UNION ALL查询的后半部分有一个“ORDER BY the_date”,但是在他们加入工会后你再做一次“ORDER BY the_date”。你只需要第二个。
另一件事...... DATE字段中没有索引,但这是所有这些的主要过滤器。例如,如果您在“click_date”上编入索引,则如果WHERE使用“DATE(click_date)”,则不会使用索引。做这样的事情会更好:
WHERE click_date BETWEEN '2013-04-01 00:00:00' AND '2013-04-30 23:59:59'
并在click_date上有一个索引。然后它可以更快地找到那些相关记录。
答案 1 :(得分:2)
您过滤(where子句)transaction.order_date
。我没有看到那些字段的索引。添加它应该已经有所作为。
此外,click_date
用于过滤,但它位于带partner_id
的单独索引(PK)中。由于您不能按partner_id
进行过滤,因此您也可以在click_date
上设置单独的索引。