Задавайте вопросы, мы ответим
Вы не зашли.
Есть запрос:
Отредактированно Proger (11.04.2009 17:08:44)
Неактивен
А можно попросить еще дамп из десятка-другого строчек?
Неактивен
Отредактированно Proger (13.04.2009 00:29:27)
Неактивен
Начнем с того, что построенный индекс не влияет на сортировку запроса, даже, выполненный в одну сторону:
EXPLAIN SELECT * FROM `topic` FORCE INDEX ( gid ) ORDER BY `pinned` ASC , `last_post_time` ASC id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE topic ALL NULL NULL NULL NULL 5 Using filesort
Теперь пробуем так:
ALTER TABLE `topic` DROP INDEX `gid`; ALTER TABLE `topic` ADD INDEX `for_sort` ( `pinned` , `last_post_time` ) ; ALTER TABLE `topic` ADD INDEX `for_search` ( `gid` , `fid` , `st` ) ; ANALYZE TABLE `topic`; EXPLAIN SELECT * FROM `topic` FORCE INDEX (for_sort) ORDER BY `pinned` ASC, `last_post_time` ASC; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE topic index NULL for_sort 9 NULL 5 EXPLAIN SELECT * FROM `topic` FORCE INDEX (for_sort) ORDER BY `pinned` ASC, `last_post_time` DESC; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE topic ALL NULL NULL NULL NULL 5 Using filesort explain SELECT * FROM `topic` FORCE INDEX (for_sort, for_search) WHERE `gid` =1 AND `fid` =6 AND `st` != 'TRASH' ORDER BY `pinned` ASC, `last_post_time` ASC id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE topic ref for_search for_search 8 const,const 1 Using where; Using filesort
Из этих опытов делаем выводы:
1. Двунаправленной сортировке все равно нужен filesort.
2. Для сортировки без filesort помимо одного направления поиска нужен свой ключ
3. Оптимизатор MySQL выбирает из двух возможных индекс именно для поиска, предпочитая сортировать результат через filesort, даже однонаправленный.
В связи с этим вопрос: зачем Вы хотите оптимизировать запрос? Вам не нравится время его выполнения или слово filesort в результатах explain? Если второе - то оставьте, filesort при десятке найденных записей не страшен. Если первое, то напишу пару запросов - у них менее красивый explain, но на большом объеме данных могут выполняться быстрее, нужно проверять.
Неактивен
Я тоже немножко встряну
В этой конструкции мне больше всего не нравится «!= TRASH», оно автоматически приводит к тому, что
индекс используется как RANGE. Как следствие, сортировка всегда происходит через filesort. Замена
на IN (...) даст возможность использовать сортировку на первом куске. DESC, к сожалению, использовать
не удастся, т.к. MySQL не умеет создавать ключи в обратном порядке (не смотря на то, что понимает
соответствующий синтаксис). Но односторонняя сортировка будет использовать индекс.
Неактивен
Ох как расписали Спасибо. Подробно!
Magz, время выполнения в 20 раз больше чем у других запросов, но и таблица пока не особо большая, потому я и обеспокоился. Неисправны индексы или логика приложения...
paulus, то есть в IN мне перечислить все нужные значения, кроме TRASH соответственно, я правильно понял? Попробую создать тогда вариант индекса, который будет объединять эти поля в одно... точнее просто заведу "служебное" поле для сортировки только один раз.
Да и я что-то не понял, но разве не надо для подобных запросов делать ОДИН индекс, который включает и поля входящие в WHERE и в ORDER BY? Разве нужно делать 2 индекса по этим частям запроса??? о.О
Неактивен
Про два индекса я ничего не говорил, на таблице используется только один индекс
Неактивен
Спасибо за помощь, уже придумал решение, filesort ушел гулять
Неактивен
Да но не надолго. Все было прекрасно в теории а на практики любой ORDER BY вызывает файлсорт, даже если ORDER BY один и идет в направлении ASC.
Собственно может у вас есть опыт как вывести темы форума отсортировав, так чтобы прикпреленные были сверху и потом отсортировать по дате эти темы? Смотреть другие движки прошу не предлагать. Смотрел - толку мало. Все запутано жутко.
Может ХП или VIEW поможет?
Особенно я встал ступором вспомнив про данный запрос:
Неактивен
Может, немного реструктуризовать табличку? А то у Вас часть данных битовая (pinned),
а часть — «в одном флаконе» (st). Логичнее сделать отдельные флажки «private»,
«erased» и т.п. Тогда не надо будет делать страшных зверей типа PRIVCLOSED.
А с индексом, к слову сказать, может быть сделать pinned «по смыслу» логическим совсем?
тогда 1 = прикреплена, 0 = не прикреплена, и (о, чудо ) сортировка нужна в ту же сторону,
что и дата.
Неактивен
Во блин и не подумал как-то ... наверное так и сделаю, а то помимо PRIVCLOSED ещё один зверь лез на создание. А так как то и проще будет...
Кстати так даже лучше... ведь статус TRASH значит что тему сунули в корзину, а если её вернут я не знаю OPEN она или CLOSED...
Сижу меняю структурку...отпишусь коль чего не получится опять с индексами. Спасибо за советы!!!
Отредактированно Proger (15.04.2009 04:16:09)
Неактивен
Ну вот сел... реализовал частично что получил.
Теперь Лента форума выводится корректно (также как и раньше, и мы получаем желаемый результат) запросом:
Отредактированно Proger (15.04.2009 04:55:08)
Неактивен
Проблема действительно в скобках, и сходу она, видимо, не решается.
Попробуйте и правда через самообъединение
SELECT t1.*
FROM topic t1
JOIN topic t2 USING (id)
WHERE (t1. ... = ... )
ORDER BY t2.last_post_time DESC
Не уверен, что получится, но других мыслей пока нет. Если сработает — будет
правильная сортировка, а в сочетании с LIMIT (он же будет?), будет не страшен и
«using where».
Неактивен
Получилось сделать что-то вроде:
Неактивен
Нет, я, видимо, плохо объяснил. Хотелось сделать разделение условий ограничения и
условий сортировки. Так, чтобы какие бы ни были скобки, сортировка шла по ключу.
Т.е. ORDER (t2), но WHERE (t1). И условие связи «строки совпадают» (да, по ключу id).
Я имею в виду, что пробовать хочется с
WHERE t1.private = 1 AND t1.fid IN (5, 7)
На тех данных, что Вы дали, читерство не проходит. Но, возможно, на табличках с реальными
данными будет по другому. Если не получится — надо будет часть вещей переносить
в логику приложения
UPD: Также я бы поиграл на реальных данных с лимитами и STRAIGHT_JOIN, оно, скорее всего,
все и решит.
[celestia] root test > EXPLAIN SELECT STRAIGHT_JOIN t1.* -> FROM topic t2 JOIN topic t1 FORCE INDEX (primary) USING (id) -> WHERE t1.fid IN (5, 7) -> ORDER BY t2.last_post_time DESC; +----+-------------+-------+--------+---------------+----------------+---------+------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+-------+--------+---------------+----------------+---------+------------+------+-------------+ | 1 | SIMPLE | t2 | index | PRIMARY | last_post_time | 8 | NULL | 5 | Using index | | 1 | SIMPLE | t1 | eq_ref | PRIMARY | PRIMARY | 4 | test.t2.id | 1 | Using where | +----+-------------+-------+--------+---------------+----------------+---------+------------+------+-------------+ 2 rows in set (0.00 sec)
Неактивен
Данные данные мной реальные, разве что ники подменены ну и обрублены посты ибо длинные чота все попались просто по запросу ORDER BY RAND() из действующего проекта.
Лимит обычно 25, в максимальном значении 100.
Чтож будем пробывать, но не сегодня, запарился с JS и загрузкой проца на 100% =\ Спасибо.
Неактивен
Думаю, что у Вас больше, чем пять строк
Неактивен
дать больше может? мне не жалко просто попросили десяток, ну я выдал по быстрому только куда нить не в открытый уж источник
Неактивен
Попробуйте самостоятельно сначала
Неактивен
ммм... тупанул написав первый раз, вот что получил в результате:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t2 index PRIMARY last_post_time 8 NULL 95181 Using index
1 SIMPLE t1 eq_ref PRIMARY PRIMARY 4 forum.t2.id 1 Using where
работает вроде быстро
Отредактированно Proger (16.04.2009 00:04:30)
Неактивен
Угу, с лимитом должно работать быстро. Но в случае выборки не в начале (например, 50 страница),
запрос будет тяжелым. К счастью, 50 страницу редко запрашивают (и очень часто ограничивают
возможность выбирать по такой «ленте» разумным количеством страниц).
Неактивен
Вот только проблемы с восстановлением возвращения нужного результата пока, но вроде потихоньку продвигаюсь... вообще запрос выполняется 0.004, после первого раза, потом уже 0.001, правда один раз скакнул на 0.1. но эт глюк наверное был
ЗЫ листать у меня запрещено, просто на одной странице выводятся последние темы + они же в виде рсс с тем же ограничением.
Спасибо большое, очень помогли, а то чуть голову не сломал думая что же делать и думал что совсем кривая логика приложения, писали по пьяне и т.п. )
Неактивен
мммм... запрос так работает нормально, но как добавляю ORDER BY t1.notpinned все слетает по filesort (
Отредактированно Proger (17.04.2009 00:57:01)
Неактивен
Замутите!
«FORCE INDEX» Вам поможет Пример использования — написан Вами выше для таблички
t1, нужно то же сделать для t2.
Неактивен
Замутить - замутил.
Всё сделал. Форсе индекс поставил. EXPLAIN говорит индекс взят... все равно Using index, Using filesort на первом запросе...
Неактивен