繁体   English   中英

如何优化此查询?

[英]How can I optimize this query?

我有两个具有以下结构的mysql表:

mysql> describe symbol;
+-------------+--------------+------+-----+---------+----------------+
| Field       | Type         | Null | Key | Default | Extra          |
+-------------+--------------+------+-----+---------+----------------+
| id          | int(11)      | NO   | PRI | NULL    | auto_increment |
| symbol      | varchar(250) | NO   |     | NULL    |                |
+-------------+--------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> describe price;
+-----------+---------+------+-----+---------+----------------+
| Field     | Type    | Null | Key | Default | Extra          |
+-----------+---------+------+-----+---------+----------------+
| id        | int(11) | NO   | PRI | NULL    | auto_increment |
| id_symbol | int(11) | NO   | MUL | NULL    |                |
| date      | date    | NO   | MUL | NULL    |                |
| price     | double  | NO   |     | NULL    |                |
+-----------+---------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

我必须查询价格表以获得具有两个符号的N个价格的列表(以比较它们)

这是一个示例结果:

DATE        SYMBOL 1 SYMBOL 2
2011-01-01    100      23
2011-01-02    92       26
2011-01-03    89       50

所以我需要找到两者的相同数据并返回它们的价格。 我已经创建了一个看起来可以完成工作的查询,但可能不是很优化。

SELECT *
FROM price AS a
  JOIN price AS b ON a.date = b.date
WHERE a.id_symbol = 1 AND b.id_symbol = 2
ORDER BY a.date DESC
LIMIT 100

你怎么看?

我可以优化查询做某事(或者可能更改表结构上的某些内容)吗?

编辑:

这是EXPLAIN {query}的结果

mysql> EXPLAIN SELECT *
    -> FROM price AS a
    ->   JOIN price AS b ON a.date = b.date
    -> WHERE a.id_symbol = 1 AND b.id_symbol = 2
    -> ORDER BY a.date DESC
    -> LIMIT 100;
+----+-------------+-------+------+----------------+-----------+---------+-------+------+-----------------------------+
| id | select_type | table | type | possible_keys  | key       | key_len | ref   | rows | Extra                       |
+----+-------------+-------+------+----------------+-----------+---------+-------+------+-----------------------------+
|  1 | SIMPLE      | a     | ref  | date,id_symbol | id_symbol | 4       | const |  921 | Using where; Using filesort |
|  1 | SIMPLE      | b     | ref  | date,id_symbol | id_symbol | 4       | const |  966 | Using where                 |
+----+-------------+-------+------+----------------+-----------+---------+-------+------+-----------------------------+
2 rows in set (0.03 sec)

你怎么看?

然后...... EXPLAIN“ROW”栏中的921和966是什么? 如果我计算符号1和符号2的价格,我得到:912和912: - | 那是什么?

(PS是的,我的错误,我必须改变*我想要的列)

根据有限的信息,您可以做的就是在id_symbol ASC, date DESC上创建一个索引id_symbol ASC, date DESC并可能将*仅限制为您需要的列。

您最大的“加速”可能是将两个查询合并为一个查询,然后运行该查询并解析结果集而不是运行一个查询以获取所有符号对,然后对每个符号对进行不同的查询。 您不提供原始查询,因此无法建议此组合查询。

这是您的原始查询

SELECT *
FROM price AS a
JOIN price AS b ON a.date = b.date
WHERE a.id_symbol = 1 AND b.id_symbol = 2
ORDER BY a.date DESC
LIMIT 100;

您需要进行两项重大更改:

改变#1:改造你的查询

仅使用键,首先发生WHERE,ORDER BY,JOIN持续

SELECT A.date,GROUP_CONCAT(A.price ORDER BY A.id_symbol) prices
FROM price A
INNER JOIN
(
  SELECT BB.* FROM
  (
    SELECT DISTINCT date FROM
    (
       SELECT AAAA.date FROM
       (SELECT date FROM price WHERE id_symbol = 1) AAAA
       INNER JOIN
       (SELECT date FROM price WHERE id_symbol = 2) BBBB
       USING (date)
       ORDER BY AAAA.date
    ) AAA ORDER BY date DESC LIMIT 100
  ) AA
  INNER JOIN
  (SELECT date,id_symbol FROM price WHERE id_symbol in (1,2)) BB
  USING (date)
  ORDER BY BB.date DESC,BB.id_symbol
) B
USING (date,id_symbol) GROUP BY date;

更改#2:创建索引以支持经过改造的查询

ALTER TABLE price ADD INDEX symbol_date_id_ndx (id_symbol,date,id);
ALTER TABLE price ADD INDEX date_id_ndx (date,symbol_id);

试试看 !!!

撇开关于过早优化的可能非常合适的评论,您是否尝试使用EXPLAIN( http://dev.mysql.com/doc/refman/5.1/en/using-explain.html )来查看您的查询是如何实际执行的? 从那里你可能想要考虑添加索引。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM