Правила     Закладки     Карма    Календарь    Журналы    Помощь    Поиск    PDA    Чат   
        СМС-ки
   
Пейджер выключен!
 
Фильтр авторов:    показать 
  скрыть
  Ответ в темуСоздание новой темыСоздание опроса

> Простой индекс, MySQL
forza  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 406
Пользователь №: 23841
На форуме: 14 лет, 7 месяцев, 20 дней
Карма: 22




Добрый день.

Не знаю, не могу разобраться с глупой проблемой. Почему не используется индех при элементарной выборке?
Структура таблицы:

Цитата
CREATE TABLE `sc_webdata_main` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `domain` varchar(150) NOT NULL,
  `idn` varchar(150) NOT NULL,
  `md5domain` varchar(32) NOT NULL,
  `added_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `modified_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  `price` decimal(30,2) unsigned NOT NULL,
  PRIMARY KEY (`id`),
  KEY `ix_md5domain` (`md5domain`),
  KEY `ix_added` (`added_at`),
  KEY `ix_price` (`price`)
) ENGINE=InnoDB AUTO_INCREMENT=10999 DEFAULT CHARSET=utf8


Запрос:
explain select * from sc_webdata_main order by price desc limit 300, 10;

Результат:

+----+-------------+-----------------+------+---------------+------+---------+------+-------+-------- --------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+------+---------------+------+---------+------+-------+------- ---------+
| 1 | SIMPLE | sc_webdata_main | ALL | NULL | NULL | NULL | NULL | 11184 | Using filesort |
+----+-------------+-----------------+------+---------------+------+---------+------+-------+------- ---------+



Не понимаю почему по-умолчанию не используется индех (ix_price) и mysql сканирует все записи?

С таким вариантом выглядит лучше:
explain select * from sc_webdata_main force index (ix_price) order by price desc limit 3000, 1

Результат:

+----+-------------+-----------------+-------+---------------+----------+---------+------+------+----  ---+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-----------------+-------+---------------+----------+---------+------+------+--- ----+
| 1 | SIMPLE | sc_webdata_main | index | NULL | ix_price | 14 | NULL | 3010 | |
+----+-------------+-----------------+-------+---------------+----------+---------+------+------+--- ----+


Можно ли как-то обойтись без force index и почему даже если используется индекс - сканируются 3000 тыс. строк вместо 10? или я не совсем понимаю принцип работы...


--------------------
Заработок для веб-разработчиков: CodeCanyon
Мое Портфолио
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
T1grOK  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 2804
Пользователь №: 24406
На форуме: 14 лет, 6 месяцев, 11 дней
Карма: 181




ПО умолчанию, Mysql, за редким исключением, очень тупо применяет(или не применяет) индекс к сортируемым полям. Честно говоря буквально пару раз в своей жизни видел, чтобы Mysql нормально применил индекс к сортируемому полю.

Понятное дело, там шуршит анализатор, оптимизатор, которые принимают решения по целесообразности той или иной стратегии выполнения запроса, но блин, эти решения однобоки))


--------------------
Mysql, Postgresql, Redis, Memcached, Unit Testing, CI, Kohana, Yii, Phalcon, Zend Framework, Joomla, Open Cart, Ymaps, VK Api
PMПисьмо на e-mail пользователюСайт пользователя
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
GET  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



TERRAFORMING ENGINEER
******

Профиль
Журнал
Группа: ★ЛжеЭксперт★
Завсегдатай форума
Сообщений: 3900
Пользователь №: 21196
На форуме: 15 лет, 1 месяц, 25 дней
Карма: 88




Цитата
ПО умолчанию, Mysql, за редким исключением, очень тупо применяет(или не применяет) индекс к сортируемым полям.


Тоже хотел что-то подобное написать, но постеснялся. Есть таблица на сайте к которой применяет (там участвует WHERE), а в другой не применяет, так и не понял почему.


--------------------
Не тот велик, кто не падал, а тот кто падал и поднимался.
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
forza  
 ۩  Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Здесь живет
******

Профиль
Группа: Форумчанин
Завсегдатай форума
Сообщений: 406
Пользователь №: 23841
На форуме: 14 лет, 7 месяцев, 20 дней
Карма: 22




ОК. Понятно, значит буду использовать конструкцию с "force index" (см. 2ой пример). Но такой вопрос. Если offset будет стоять 1 миллион, то он сначала переберет 1 миллион записей, а потом вернет 10 требуемых? Нельзя ли как-то оптимизировать этот процесс?


--------------------
Заработок для веб-разработчиков: CodeCanyon
Мое Портфолио
PMПисьмо на e-mail пользователю
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
sergeiss  
Дата
Цитировать сообщение

Пользователя сейчас нет на форуме



Сидел он, дум великих полон - и вдаль глядел
******

Профиль
Группа: Эксперт
Группа переписки
Сообщений: 15860
Пользователь №: 4190
На форуме: 17 лет, 2 месяца, 22 дня
Карма: 490




Цитата (forza @ 11.12.2014 - 19:08)
Если offset будет стоять 1 миллион, то он сначала переберет 1 миллион записей, а потом вернет 10 требуемых? Нельзя ли как-то оптимизировать этот процесс?

А ты как хотел? Всё очень логично получается. Откуда запрос может узнать, какие именно 3000 записей пропустить? Только из того, что их перебрать. Так что то, что ты описал, это нормальная работа limit в БД.

Оптимизировать можно, но не во всех случаях. Например, если ты знаешь, какое у тебя было предыдущее значение, например, по полю price (в предыдущей подобной выборке, допустим при постраничной навигации, пусть это было число 1436.78). Тогда ты можешь написать так
select * from sc_webdata_main 
where price < 1436.78
order by price desc limit 1

При таком запросе будет обработана всего одна строка. Но это, как я уже сказал, "особый случай".

Можно попробовать выбрать этот порог подзапросом с лимитом "3000, 1", но там выбирать не всё, а только одно поле. Возможно, что это будет сделано быстрее (потому что в подзапросе будет выбираться существенно меньше данных). Но надо проверить, какая будет скорость.

select * from sc_webdata_main 
where price < (select price from sc_webdata_main order by price desc limit 3000, 1)
order by price desc limit 1



--------------------
* Хэлп по PHP
* Описалово по JavaScript
* Хэлп и СУБД для PostgreSQL

* Обучаю PHP, JS, вёрстке. Интерактивно и качественно. За разумные деньги.

* "накапливаю умение телепатии" (С) и "гуглю за ваш счет" (С)

user posted image
PMICQ
    0   Для быстрого поиска похожих сообщений выделите 1-2 слова в тексте и нажмите сюда Для быстрой цитаты из этого сообщения выделите текст и нажмите сюда
  Быстрый ответ
Информация о Госте
Введите Ваше имя
Кнопки кодов
Для вставки цитаты, выделите нужный текст и
НАЖМИТЕ СЮДА
Введите сообщение
Смайлики
:huh:  :o  ;) 
:P  :D  :lol: 
B)  :rolleyes:  <_< 
:)  :angry:  :( 
:unsure:  :blink:  :ph34r: 
     
Показать всё

Опции сообщения  Включить смайлики?
 Включить подпись?
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:

Опции темы Ответ в темуСоздание новой темыСоздание опроса