Задавайте вопросы, мы ответим
Вы не зашли.
Добрый день. Подскажите пожалуйста почему опримизатор упорно не хочет использовать индекс в следующем запросе:
Неактивен
Быть может оптимизатор счетает что использовать индекс при выборке того объема данных что находятся в таблице не рентабельно и проще сделать полный скан? Хотя если делать ту же выборку по полю id то все работает как надо.
Неактивен
Подозреваю, что у Вас количество записей, для которых ping > 25 настолько велико (по сравнению с остальными), что оптимизатор считает, что дешевле сделать FTS.
Неактивен
Да нет, записей как раз не много, я сейчас эксперементировал с разным кол-вом записей,100, 1000, 10000 и.т.д эффект тот же, правда колонка rows стала показывать немного меньше кол-во записей затронутых в запросе, но это все равно полный скан. Даже уникальный не помогает.
Неактивен
А Вы попробуйте обновить статистику индекса запросом analyze table demands.
Сколько у Вас в таблице записей, у которых ping > 25?
Сколько всего записей в таблице?
explain запроса покажите пожалуйста.
Неактивен
Обновил статистику, не помогло. Вот explain на таблицу с 10000 записей: select_type=SIMPLE table=demands type=ALL possible_keys=ping key=NULL key_len=NULL ref=NULL rows=8395 Extra=Using where.
Неактивен
Ну правильно - у Вас записей, годящихся под условие 8395 из 10000. Тут куда проще и быстрее сделать FTS, что mysql и делает ). Поменяйте условие например, на "ping < 25", другой explain?
Неактивен
Да когда пишу <25 то все работает как надо, rows кажет 24 и type range ,но если пишу скажем >9000 или любое число то rows все равно кажет 8395, ping содержит записй от 1 до 10000 по возрастанию
Неактивен
Можете приложить структуру и данные таблички сюда (если там нет ничего секретного)?
Неактивен
А если ставлю ping<5000 или > то rows выдает 10445, откуда берутся эти 445 строк? А что за структура таблица? Приложить не могу, так как с КПК пишу в данное время.
Неактивен
Это вообщем таблица заявок данные хранятся так: id=ид.заявки, symbol=тикер, type=тип заявки(купить,продать) price=цена amount=кол-во user=логин ping=копия ид. Структуру таблицы я описал в 1 посте данного топика, если конечно это структура
Неактивен
Удалил столбцы из таблицы, оставил только столбец id и ping и о чудо индекс наконец заработал как надо. Кошмар какой то. Пробовал добавлять составной индекс опять начинается полный скан. Что за ерунда у меня в компе происходит может кто нибудь объяснить?!
Неактивен
simple написал:
А если ставлю ping<5000 или > то rows выдает 10445, откуда берутся эти 445 строк? А что за структура таблица? Приложить не могу, так как с КПК пишу в данное время.
Оптимизатор лишь оценивает количество строк, которые вернет запрос. Поэтому число неточное. Если у вас нужно выбрать 8000 из 10000 строк, то лучше перебрать все (чтение диска будет последовательным), чем перескакивать 8000 раз по индексу. Поэтому поведение оптимизатора правильное. id отличается тем, что это первичный ключ - обращение по нему происходит быстрее, чем по вторичному, поэтому решение оптимизатора может быть другим.
Представьте себе, что у вас список 10000 записавшихся на просмотр фильма. Из них нужно исключить 1000 не достигших 18 лет. Вариант с индексом - у вас отдельный список id упорядоченный по возрастам, начинаете с 18 лет, находите соответствующую фамилию в полном списке, выписываете и так последовательно по всем возрастам - при этом нужно переходить от индекса (списка возрастов) к основной таблице по указателю id. Второй вариант - читать основной список и выписывать из него только тех, кому >= 18. Случай бумажного носителя аналогичен жесткому диску - вариант с индексом потребует больше листать (передвигать головку). Если бы данные хранились в памяти, индекс не приводил бы к таким дополнительным затратам.
Неактивен
Добавил в запрос FORCE INDEX индекс ping наконец то заработал, ура. Но...вкрались сомнения а правильно ли я поступил лишив оптимизатор свободы выбора в выборке, может лучше доверится оптимизатору и оставить все как есть, ведь на то он оптимизатор и ему видней?
Неактивен
rgbeast, спасиво Вы меня убедили, оставля запрос как есть.
Неактивен
А если мне не нужно выберать 8000 записей из 10000 (хотя в исключительной ситуации это может потребоваться), так как условие ping>25 это не константа, по мере заполнения таблицы условия с ping тоже будет увеличиваться, скажем условие ping>9900 для таблицы из 10000 записей, полный скан таблицы тоже будет оправдан?
Неактивен
Оптимизатор будет решать использовать индекс или нет для конкретного случая (наполненности таблицы и числа 25). Если нет прямого указания, что он ошибается (сравните скорость с FORCE INDEX и c IGNORE INDEX), то ему можно доверять.
Неактивен
Дело в том что я эксперементировал с разным количеством записей и с разными условиями и все равно идет полный скан. Просто мозгу моему с трудом понимается, как это если скажем таблица достигла размера 50000 записей и нужно выбрать записи где ping >49900, т.е 100 последних записей полный скан будет дешевле.
Отредактированно simple (10.06.2011 00:49:16)
Неактивен
Например для ping<25 вы писали, что используется индекс. Индекс оправдан обычно только для небольшого количества выбираемых строк. Вопрос имеет смысл, если записей столько, что один из вариантов (FORCE INDEX или IGNORE INDEX) работает существенно медленнее, чем второй. Протестируйте время исполнения на более большой таблице. Тут возможна ошибка оптимизатора, если статистика индексов неточна, но заставить обходить по индексу всю или почти всю таблицу значительно хуже в плане производительности (проверьте)
Неактивен
А как сравнить скорость? У меня клиент в обоих случаях выборки 0.000 sec кажет.
Неактивен
Надо добиться того, чтобы было больше, чем 0.000, иначе сам вопрос теряет смысл. Например, увеличить таблицу в 100 раз. И не забывайте SELECT SQL_NO_CACHE, чтобы из кэша не получать.
Неактивен
Протестил на таблице с 50000 записей с условием ping>49950 FORCE INDEX показывает время 0.000 sec, IGNORE INDEX 0.063 sec, при условии ping>25000, 0.016 sec (+0.234 sec. Network) и 0.016 sec (+0.172 sec network) соответственно.
Неактивен
А что выбирает оптимизатор в этих случаях, если сделать OPTIMIZE TABLE;
Неактивен
Вобщем мне и не нужно переберать всю таблицу, а нужно только выбирать те записи у которых ping больше прошлого сох.значения ping, это своего рода пеленгатор последних вставленых записей или обновленных. Спасибо, rgbeast, помог разобраться наконец то в этих дебрях
Неактивен
После optimize table так же кажет, 0.016 для force 0.063 ignore, так что выбираем force так как мне нужен именно конец таблицы и пусть оптимизатор отдохнет
Неактивен