Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Есть запрос:
Отредактированно Proger (14.02.2009 22:22:00)
Неактивен
Попробуйте FORCE INDEX. Оптимизатор считает, что один раз пройти всю таблицу проще, чем 500 раз пройти по индексу, и, возможно, это правда.
Неактивен
гм... Индекс подцепил но все равно using_filesort. Размер таблицы переменно от 100 до 100000 записей. Возможно следует изменить алгоритм сам вот только как...
Кто быстрее не понять особо, но в slow-query падает же ( попробую поставить на время FORCE_INDEX может не будет падать...
UID = это ID друзей данного пользователя и я вывожу информацию о том что они за последнее время сделали. Иного алгоритма пока не придумал, попробую пообсуждать.
Отредактированно Proger (14.02.2009 23:32:58)
Неактивен
Proger написал:
но все равно using_filesort
Потому что сортируете по полю `TIME`, которое не входит в левый префикс ни одного из ключей.
Отредактированно coin (14.02.2009 23:37:53)
Неактивен
ммм. Что за левый префикс, можно тогда "правильный индекс" в студию. Что-то я не допонял...
Неактивен
Индексы сортируются примерно так:
`uid` `TIME` 0 2009-02-14 23:59:47 0 2009-02-14 23:59:47 0 2009-02-15 00:06:47 1 2009-02-14 23:58:47 1 2009-02-15 00:01:47 1 2009-02-15 00:07:47 2 2009-02-15 00:07:47 3 2009-02-15 00:08:47 4 2009-02-15 00:05:47 4 2009-02-15 00:07:47 5 2009-02-15 00:06:47 6 2009-02-15 00:00:47 6 2009-02-15 00:01:47 6 2009-02-15 00:05:47 7 2009-02-15 00:01:47
Т.е. происходит общая сортировка по первому полю и у групп с равными `uid` записи отсортированы по второму полю `TIME`. А вы хотите от такого индекса общую сортировку по второму полю.
С этим индексом можно работать только по левому префиксу полей:
1) либо `uid`
2) либо `uid`,`TIME`
Насчёт правильного индекса врятли помогу..
Неактивен
Если запрос был бы ... WHERE uid=10 ORDER BY time
то составной индекс сработал бы. Однако это возможно только если все операции, кроме последней - точное равенство (а не >,<, IN)
Неактивен
Я бы создал индекс `TIME`,`uid` и использовал бы запросы вроде:
SELECT *
FROM `infosystem` USE INDEX (`имя индекса`)
WHERE
`TIME` BETWEEN CURRENT_DATE-INTERVAL 5 DAY AND CURRENT_DATE-INTERVAL 4 DAY
AND
`uid` IN ( 2, 4, 5, 6, 7, 16, 18, 20, 24, 26, 32, 33, 34, 37, 38, 39, 42, 44, 45, 66, 67, 68, 71, 73, 1001, 1002, 1005 )
ORDER BY `TIME`
Т.е. что то вроде постраничной навигации по суткам.
Неактивен
coin, вторая часть индекса использоваться в Вашем случае все равно не будет
Неактивен
coin, сделал так (индекс не подрубился). Навигация по дням мне тут не пригодится. Но в другом месте уже пригодилась - спасибо.
Вот только не понимаю чего делать ибо индексы не работаюсь, а какой тогда алгоритм выбирать фигзнает ((
Пользователь делает что-то, например пишет другому комментарий на запись в блоге и это добавляется в таблицу infosystem и как бы тут же любой друг этого пользователя может это увидеть (на странице "новости друзей") и пройти почитать его комментарий и ту запись в блоге которую он комментировал. Как тут иначе то сделать? Создавать по записи на каждого друга? А если друзей 1000 ? ммм... я погряз в глубоких раздумьях...
Отредактированно Proger (15.02.2009 00:58:29)
Неактивен
rgbeast, для сортировки не будет (и не надо), а для выборки помоему должна, почему нет?
Отредактированно coin (15.02.2009 00:55:14)
Неактивен
КСТАТИ! Я тут подумал. А если сортировать на стороне php? То есть только выборку по UID IN() сделать, а отсортировать уже в php?
Ну да... наверное это самый оптимальный вариант. Только не FORCE INDEX, а USE чтобы оптимизатор сам там подумал что быстрее. Использовать кучу проходов по индексу или по таблице.
Отредактированно Proger (15.02.2009 01:21:10)
Неактивен
Т.е. выборка вообще ничем не ограничивается? Если есть 1000 записей - все выводить?
/ Не думаю что у PHP сортировка 2мерного ассоциативного массива выйдет быстрее )
Неактивен
дык данные об активности людей автоматом чистятся. И выводится за последние несколько дней примерно.
Притом данные ещё проходят парсер. Который например группирует одинаковые события. Например человек загрузил 100 фотографий мне что о каждой фотке отдельный раз информацию вывести? Нет я просто беру и пишу юзер "загрузили фото (N штук)".
Тут вопрос даже не в скорости, а в том чтобы запрос не падал в slow-query-log ибо мешает следить за другими неполадками.
Также подумываю сделать кеширование материала, чтобы генерировать всю информацию и парсить её в том числе один раз, а не при каждом просмотре.
Неактивен
Извините, немножко вклинюсь.
1. На таблице InnoDB нет явного primary key - это плохо.
2. Второй индекс полностью включает в себя первый. Первый индекс можно смело снести.
Без первичного ключа данные лежат тостаточно хаотично (и уж точно не в порядке id).
Когда оптимизатор пытается решить, что лучше - выбрать 30 строк из 150 по хаотичным
данным или прочитать все и отсортировать - он предпочитает второе. Оно, разумеется, быстрее.
Неактивен
Вообще, операция IN сама по себе долгая. Как я понимаю, набор значений, которые подставляются в IN получаются на основе каких-то запросов? Не получится ли сделать примерно так:
SELECT field FROM (SELECT значения_которые_в_IN FROM tables WHERE условия_использующие_индексы) t1 JOIN infosystem ON infosystem.uid = t1.данные
ИМХО, в этом случае индексы должны будут использоваться гораздо эффективнее. По крайней мере, у меня скорость подобного запроса на 2 000 000 строчках выросла с 4-5 минут до 5-7 секунд. Правда, это было на оракле, но не думаю, что в данном случае будет разница.
Неактивен
paulus - примари индекс нарисовал, индекс первый потёр, а какие ещё варианты? То что предложил Magz?
Magz - верно, я выбираю сначала список друзей, потом генерирую запрос. И уже сейчас понял что это неверное вообще бить на запросы было. хм...
ЗЫ в slow query log кстати падали абсолютно все запросы почему-то. Но данный запрос всё равно не верен - факт.
Отредактированно Proger (24.02.2009 08:46:09)
Неактивен
Ну в slow log он падает потому что у Вас или очень-очень медленный сервер, или таки включена запись
запросов без индексов. Для маленьких табличек - это нормально.
Неактивен
Странно в slow-query падало всё подряд (вырубил просто slow-query ибо падали запросы даже системные самого мускуля к базе mysql и information_schema). Однако EXPLAIN плохой только на нескольких запросах...
Сервер нормальный, загрузка в среднем не более 10% процессора. И оперативка на одну пятую только занята во время основных нагрузок на сервер.
ADD: да была включена запись запросов без индексов.
Отредактированно Proger (24.02.2009 19:17:26)
Неактивен
Magz написал:
Вообще, операция IN сама по себе долгая.
Операция IN нормальная, быстрая.
Прекрасно понимает индексы.
Проблемы возникают если источник IN не константа - подзапрос.
Оптимизатор MySQL криво их отрабатывает, может выполнить его далеко не один раз.
http://sqlinfo.ru/forum/viewtopic.php?id=559
Я эту проблему для себя решил
Подобные конструкции заворачиваю в ХП.
Разбиваю на два запроса.
Сначала выполняю подзапрос, результат загоняю в строку через GROUP_CONCAT.
SELECT GROUP_CONCAT(bla) FROM blabla WHERE id = 1 INTO blablabla;
Затем собираю строку основного запроса
@qry = CONCAT("SELECT id FROM test WHERE test.bla IN (" , blablabla, ")";
Дальше через PREPARE его выполняю
http://sqlinfo.ru/forum/viewtopic.php?id=363
В результате жестко выполняю подзапрос ОДИН раз и не имею проблем с оптимизатором.
Неактивен
EugeneTM написал:
Magz написал:
Вообще, операция IN сама по себе долгая.
Операция IN нормальная, быстрая.
Прекрасно понимает индексы.
Я имел ввиду, что поиск каждого значения из IN происходит по полной таблице. Да, индекс, конечно, используется, но запорс, где в IN стоит два значения практически равен двум отдельным запросом. Вернее, сопоставим с выполнением двух отдельных запросов с равенством. И чем больше значений в IN, тем тяжелее получается запрос. Естественно, это заметно на больших объемах данных.
SELECT * FROM Table WHERE f IN (1,2) // Сопоставим с SELECT * FROM Table WHERE f =1 UNION SELECT * FROM Table WHERE f =2
Возможно, я не прав, к этому выводу я пришел самостоятельно после большого числа экспериментов.
Отредактированно Magz (26.02.2009 11:25:29)
Неактивен
В приведенном примере второй запрос будет работать дольше, т.к. будет
использоваться временная таблица.
Неактивен
Ну, я написал просто, как иллюстрацию своих слов. Естественно, оптимизатор работает не так Главное, что сопоставимо.
Неактивен
Magz написал:
EugeneTM написал:
Magz написал:
Вообще, операция IN сама по себе долгая.
Операция IN нормальная, быстрая.
Прекрасно понимает индексы.Я имел ввиду, что поиск каждого значения из IN происходит по полной таблице. Да, индекс, конечно, используется, но запорс, где в IN стоит два значения практически равен двум отдельным запросом. Вернее, сопоставим с выполнением двух отдельных запросов с равенством. И чем больше значений в IN, тем тяжелее получается запрос. Естественно, это заметно на больших объемах данных.
Код:
SELECT * FROM Table WHERE f IN (1,2) // Сопоставим с SELECT * FROM Table WHERE f =1 UNION SELECT * FROM Table WHERE f =2Возможно, я не прав, к этому выводу я пришел самостоятельно после большого числа экспериментов.
Не прав
Explain посмотри, по сути то же самое что и WHERE id = const
PS.
В него вообще почаще заглядывать нужно, он может фингню делать, но как правило не врет.
В смысле что пишет, то и делает
Неактивен
Страниц: 1