2012-04-24 150 views
3

我有这个疑问:我可以优化这种查询吗?

SELECT 
    s.last_spread, s.sd, s.mean, s.id 
    ,c.id_ticker, c.coef 
    ,t.ticker 
    ,p.last, p.price 

FROM (SELECT * FROM spreads WHERE spreads.id_check=1 LIMIT 100,500) as s 

    INNER JOIN coef as c 
     ON c.id_spread = s.id 

    INNER JOIN tickers AS t 
      ON t.id = c.id_ticker 

    LEFT JOIN (SELECT prices.id_ticker, MAX(prices.date) as last, prices.price FROM prices GROUP BY prices.id_ticker) AS p 
      ON p.id_ticker = t.id 

这些表的模式:

mysql> desc spreads; 
+-------------+---------+------+-----+---------+----------------+ 
| Field  | Type | Null | Key | Default | Extra   | 
+-------------+---------+------+-----+---------+----------------+ 
| id   | int(11) | NO | PRI | NULL | auto_increment | 
| id_check | int(11) | YES | MUL | NULL |    | 
| sd   | double | YES |  | NULL |    | 
| mean  | double | YES |  | NULL |    | 
| last_spread | double | YES |  | NULL |    | 
+-------------+---------+------+-----+---------+----------------+ 
5 rows in set (0.00 sec) 


mysql> desc coef; 
+-----------+---------+------+-----+---------+----------------+ 
| Field  | Type | Null | Key | Default | Extra   | 
+-----------+---------+------+-----+---------+----------------+ 
| id  | int(11) | NO | PRI | NULL | auto_increment | 
| id_spread | int(11) | YES | MUL | NULL |    | 
| id_ticker | int(11) | YES |  | NULL |    | 
| coef  | double | YES |  | NULL |    | 
| side  | double | YES |  | NULL |    | 
+-----------+---------+------+-----+---------+----------------+ 
5 rows in set (0.00 sec) 


mysql> desc tickers; 
+----------+------------------+------+-----+---------+----------------+ 
| Field | Type    | Null | Key | Default | Extra   | 
+----------+------------------+------+-----+---------+----------------+ 
| id  | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| ticker | varchar(45)  | NO |  | NULL |    | 
| name  | varchar(150)  | NO |  | NULL |    | 
| category | varchar(150)  | NO |  | NULL |    | 
| issuer | varchar(150)  | NO |  | NULL |    | 
+----------+------------------+------+-----+---------+----------------+ 
5 rows in set (0.00 sec) 


mysql> desc prices; 
+-----------+------------------+------+-----+---------+----------------+ 
| Field  | Type    | Null | Key | Default | Extra   | 
+-----------+------------------+------+-----+---------+----------------+ 
| id  | int(10) unsigned | NO | PRI | NULL | auto_increment | 
| id_ticker | int(10) unsigned | NO | MUL | NULL |    | 
| date  | date    | NO |  | NULL |    | 
| price  | double   | NO |  | NULL |    | 
+-----------+------------------+------+-----+---------+----------------+ 
4 rows in set (0.01 sec) 

这些是上述表的索引;

mysql> show indexes from spreads; 
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| spreads |   0 | PRIMARY |   1 | id   | A   |  2299 |  NULL | NULL |  | BTREE  |   | 
| spreads |   1 | check_idx |   1 | id_check | A   |   1 |  NULL | NULL | YES | BTREE  |   | 
+---------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
2 rows in set (0.00 sec) 


mysql> show indexes from coef; 
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name   | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| coef |   0 | PRIMARY   |   1 | id   | A   |  9078 |  NULL | NULL |  | BTREE  |   | 
| coef |   1 | spread_ticker_idx |   1 | id_spread | A   |  NULL |  NULL | NULL | YES | BTREE  |   | 
| coef |   1 | spread_ticker_idx |   2 | id_ticker | A   |  NULL |  NULL | NULL | YES | BTREE  |   | 
+-------+------------+-------------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
3 rows in set (0.00 sec) 


mysql> show indexes from tickers; 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| tickers |   0 | PRIMARY |   1 | id   | A   |   100 |  NULL | NULL |  | BTREE  |   | 
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
1 row in set (0.00 sec) 


mysql> show indexes from prices; 
+--------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | 
+--------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
| prices |   0 | PRIMARY |   1 | id   | A   |  19962 |  NULL | NULL |  | BTREE  |   | 
| prices |   1 | id_ticker |   1 | id_ticker | A   |  19962 |  NULL | NULL |  | BTREE  |   | 
+--------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+ 
2 rows in set (0.15 sec) 

,这是查询的解释:

+----+-------------+------------+--------+-------------------+-------------------+---------+---------------------------+--------+-------------+ 
| id | select_type | table  | type | possible_keys  | key    | key_len | ref      | rows | Extra  | 
+----+-------------+------------+--------+-------------------+-------------------+---------+---------------------------+--------+-------------+ 
| 1 | PRIMARY  | <derived2> | ALL | NULL    | NULL    | NULL | NULL      | 500 |    | 
| 1 | PRIMARY  | c   | ref | spread_ticker_idx | spread_ticker_idx | 5  | s.id      |  90 | Using where | 
| 1 | PRIMARY  | t   | eq_ref | PRIMARY   | PRIMARY   | 4  | spreadtrading.c.id_ticker |  1 | Using where | 
| 1 | PRIMARY  | <derived3> | ALL | NULL    | NULL    | NULL | NULL      | 100 |    | 
| 3 | DERIVED  | prices  | index | NULL    | id_ticker   | 4  | NULL      | 119774 |    | 
| 2 | DERIVED  | spreads | ref | check_idx   | check_idx   | 5  |       | 2298 | Using where | 
+----+-------------+------------+--------+-------------------+-------------------+---------+---------------------------+--------+-------------+ 
6 rows in set (0.27 sec) 

我能优化呢?

谢谢!

编辑:

我想知道,如果索引和表的结构是为我上面贴的查询优化。我使用这个查询的结果是好的,它运行良好,但也许我可以优化它以增加查询的“速度”。

+3

哇。你怎么看?你有尝试过什么吗? 'EXPLAIN'输出中某些表格缺少选定的“键”不会产生标志?查询目前正在进行多长时间?你真的认为你可以转储所有的信息并获得答案吗? – eggyal 2012-04-24 14:36:44

+0

您对价格的派生查询是最大的罪魁祸首。不要在那里使用派生查询。 – 2012-04-24 14:57:25

+0

@eggyal - 那么,如果op只是发布他的查询,那么**我们**只会要求他发布表结构和计划,所以我认为这是一个非常受欢迎的改进 – Lamak 2012-04-24 14:58:32

回答

0

我想你可能会通过删除spreads子查询并将WHERE子句移动到最后获得一些结果,如下面的代码所示。这会损失您的LIMIT限制 - 也许您可以在最后加上LIMIT子句,具体取决于您在限制输出大小方面尝试达到的目标。

SELECT 
    s.last_spread, s.sd, s.mean, s.id 
    ,c.id_ticker, c.coef 
    ,t.ticker 
    ,p.last, p.price 

FROM spreads as s 

    INNER JOIN coef as c 
     ON c.id_spread = s.id 

    INNER JOIN tickers AS t 
      ON t.id = c.id_ticker 

    LEFT JOIN (SELECT prices.id_ticker, MAX(prices.date) as last, prices.price FROM prices GROUP BY prices.id_ticker) AS p 
      ON p.id_ticker = t.id 
WHERE s.id_check = 1 
+0

我没有注意到这一点,但'prices.price'既没有分组也没有包装在一个聚合函数中 - 这意味着它返回一个'随机'行 - 你有任何建议来解决这个问题吗? – 2012-04-24 18:42:48