Mysql отбор крайне медленный (кажется, не использует индексы) - PullRequest
1 голос
/ 21 декабря 2010

Этот запрос не завершен в разумные сроки:

mysql> select * from prices where symbol='GOOG' and date in
(select max(date) from prices where symbol='GOOG' and yearweek(date) > 201001
 group by yearweek(date));

'цены' отключены от идентификатора и имеют вторичный уникальный индекс (символ, дата):

mysql> show index 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         |      468915 |     NULL | NULL   |      | BTREE      |         |
| prices |          0 | SECONDARY_INDEX |            1 | date        | A         |       10905 |     NULL | NULL   | YES  | BTREE      |         |
| prices |          0 | SECONDARY_INDEX |            2 | symbol      | A          |      468915 |     NULL | NULL   | YES  | BTREE      |         |
+--------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set (0.00 sec)

При просмотре вывода EXPLAIN кажется, что MySql не использует индекс (дата, символ). Требует ли комбинация символа WHERE = 'GOOG' и даты IN (...)) полного сканирования таблицы и не использует вторичный уникальный индекс?

mysql> EXPLAIN select * from prices where symbol='GOOG' and date in (select max(date) from prices where symbol='GOOG' and yearweek(date) > 201001 group by yearweek(date));
+----+--------------------+--------+-------+---------------+-----------------+---------+------+--------+-----------------------------------------------------------+
| id | select_type        | table  | type  | possible_keys | key             | key_len | ref  | rows   | Extra                                                     |
+----+--------------------+--------+-------+---------------+-----------------+---------+------+--------+-----------------------------------------------------------+
|  1 | PRIMARY            | prices | ALL   | NULL          | NULL            | NULL    | NULL | 468915 | Using where                                               |
|  2 | DEPENDENT SUBQUERY | prices | index | NULL          | SECONDARY_INDEX | 17      | NULL | 468915 | Using where; Using index; Using temporary; Using filesort |
+----+--------------------+--------+-------+---------------+-----------------+---------+------+--------+-----------------------------------------------------------+
2 rows in set (0.00 sec)

Ответы [ 3 ]

2 голосов
/ 21 декабря 2010

Попробуйте присоединиться:

SELECT 
    prices.* 
FROM 
    prices 
        JOIN
            (SELECT MAX(date) AS maxdate FROM prices WHERE symbol='GOOG' AND yearweek(date) > 201001 GROUP BY yearweek(date)) 
        AS sub ON prices.date = sub.maxdate
WHERE 
    symbol='GOOG' ;

Но yearweek () по-прежнему будет проблемой, MySQL не может использовать индекс для этого. Может помочь пересчет этого значения (с использованием триггера), сохранение его в дополнительном столбце и индексирование этого столбца.

0 голосов
/ 21 декабря 2010

yearweek () отключает индекс по дате столбца.

Попробуйте изменить его на:

and date > date'2010-01-09'

... где 2010-01-09 - последний день недели 201001. Остерегайтесь отметок времени в столбце.

0 голосов
/ 21 декабря 2010

Разве вы не можете просто сделать это?

  SELECT *
    FROM prices
   WHERE symbol = 'GOOG'
     AND date >  '2010-12-18 23:59:59'
ORDER BY date DESC
GROUP BY yearweek(date)
   LIMIT 1
...