2015-06-25 9 views
0

У меня есть запрос MySQL (на самом деле MariaDB), который работает намного медленнее и возвращается на filesort при попытке сортировки по полю DATETIME (sighted) вместо первичного ключа. У меня есть индекс на sighted, но по какой-то причине он, похоже, не использует его. Как я могу индексировать эту таблицу, чтобы ее можно было эффективно отсортировать по полю DATETIME?Взаимодействующий тяжелый запрос MySQL замедляется при сортировке по дате, а не медленной сортировке по ID

select 
    user_id , t.name, f.value, y.name 
    from posts p 
     left join taxon_sightings t on (t.post_id = p.id) 
     left join fields f on (f.foreign_id = t.id) 
     left join fieldtypes y on (y.id = f.fieldtype_id) 
    group by p.id 
    order by p.sighted desc 
    limit 10; 

Когда я сортирую по полю sighted DATETIME:

MariaDB [dbase]> explain [yadda yadda, as above] 
+----+-------------+-------+--------+---------------+------------+---------+--------------------------------+------+---------------------------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref       | rows | Extra       | 
+----+-------------+-------+--------+---------------+------------+---------+--------------------------------+------+---------------------------------+ 
| 1 | SIMPLE  | p  | ALL | NULL   | NULL  | NULL | NULL       | 1759 | Using temporary; Using filesort | 
| 1 | SIMPLE  | t  | ref | post_id  | post_id | 4  | dataportal_test.p.id   | 12 |         | 
| 1 | SIMPLE  | f  | ref | foreign_id | foreign_id | 4  | dataportal_test.t.id   | 6 | Using where      | 
| 1 | SIMPLE  | y  | eq_ref | PRIMARY  | PRIMARY | 4  | dataportal_test.f.fieldtype_id | 1 | Using where      | 
+----+-------------+-------+--------+---------------+------------+---------+--------------------------------+------+---------------------------------+ 

Сравните, когда я сортировать по ID:

+----+-------------+-------+--------+---------------+------------+---------+--------------------------------+------+-------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref       | rows | Extra  | 
+----+-------------+-------+--------+---------------+------------+---------+--------------------------------+------+-------------+ 
| 1 | SIMPLE  | p  | index | NULL   | PRIMARY | 4  | NULL       | 1 |    | 
| 1 | SIMPLE  | t  | ref | post_id  | post_id | 4  | dataportal_test.p.id   | 12 |    | 
| 1 | SIMPLE  | f  | ref | foreign_id | foreign_id | 4  | dataportal_test.t.id   | 6 | Using where | 
| 1 | SIMPLE  | y  | eq_ref | PRIMARY  | PRIMARY | 4  | dataportal_test.f.fieldtype_id | 1 | Using where | 
+----+-------------+-------+--------+---------------+------------+---------+--------------------------------+------+-------------+ 
+1

Это звучит как проблема с индексом. Вы добавили индекс в столбец datetime, чтобы он мог оптимизировать запрос? Ум разделяет определение таблицы? – MiltoxBeyond

+0

Да, я это сделал, но он не использует его (это путает!). – schnauss

+0

Пожалуйста, предоставьте 'SHOW CREATE TABLE' для таблиц. –

ответ

0

Я не думаю, что вы можете. Единственный трюк, который я могу думать о том, чтобы попробовать это:

select user_id, t.name, f.value, y.name 
from posts p left join 
    taxon_sightings t 
    on (t.post_id = p.id) left join 
    fields f 
    on (f.foreign_id = t.id) left join 
    fieldtypes y 
    on (y.id = f.fieldtype_id) 
group by p.sighted, p.id 
---------^ very important 
order by p.sighted desc 
limit 10; 

Затем включите индекс на posts(sighted, id). group by с order by может воспользоваться индексом. Если тебе повезет. , ,

0

Предполагая, что p.id уникален в posts, давайте избавимся от GROUP BY p.id. Я предполагаю, что единственной причиной его существования является то, что JOINs раздувают число строк?

Избавьтесь от LEFT, если вам это нужно.

SELECT x.user_id, t.name, f.value, y.name 
    FROM 
     (SELECT id, sighted 
      FROM posts 
      -- No GROUP BY needed if id is UNIQUE 
      ORDER BY sighted DESC 
      LIMIT 10 
    ) AS p 
    JOIN taxon_sightings t ON (t.post_id = p.id) 
    JOIN fields f ON (f.foreign_id = t.id) 
    JOIN fieldtypes y ON (y.id = f.fieldtype_id) 
    GROUP BY p.id 
    ORDER BY p.sighted DESC, p.id DESC; 

И (как говорит Гордон), есть INDEX(sighted, id).