Проверките в индекса са по стойност , а не по позиция . Индексът може да търси стойност 2955900, но вие не искате това. Искате заявката да започне от отместване на 2955900-ия ред в таблицата.
Оптимизаторът не може да приеме, че всички стойности на първичния ключ са последователни. Така че е много вероятно 2955900-тият ред да има стойност много по-висока от тази.
Дори ако стойностите на първичния ключ са последователни, може да имате условие WHERE, което отговаря само на 45% от редовете. В този случай стойността на идентификатора на 2955900-ия ред ще бъде начин след стойността на идентификатора 2955900.
С други думи, търсенето в индекс на стойността на идентификатора 2955900 няма да достави 2955900-ия ред.
Така че MySQL не може да използва индекса за отместване на ограничение. трябва сканирайте редовете, за да ги преброите, докато достигне отместване+лимит редове.
MySQL има оптимизации, свързани с LIMIT , но става дума по-скоро за спиране на сканиране на таблица, след като достигне броя на редовете за връщане. Оптимизаторът все пак може да отчете в план EXPLAIN, че очаква може трябва да сканирате цялата таблица.
Често недоразумение относно FORCE INDEX е, че принуждава използването на индекс. :-)Всъщност, ако заявката не може използвайте индекс (или ако наличните индекси нямат полза за тази заявка), FORCE INDEX няма ефект.
Отново вашия коментар:
Пагинацията е често проклятие на управляваните от данни уеб приложения. Въпреки че тази функция е често срещана, не е лесно да се оптимизира. Ето няколко съвета:
-
Защо питате с изместване 2955900? Наистина ли очаквате потребителите да преглеждат толкова много страници? Повечето потребители се отказват след няколко страници (колко точно зависи от типа приложение и данните).
-
Намалете броя на заявките. Вашата функция за пагинация може да извлече първите 5-10 страници, дори ако показва само първата страница на потребителя. Кеширайте другите страници с допускането, че потребителят ще премине през няколко страници. Само ако те преминат покрай кеширания набор от страници, приложението ви трябва да направи друга заявка. Можете дори да кеширате всички 10 страници в Javascript в браузъра на клиента, така че щракването върху „Напред“ е мигновено за тях (поне за първите няколко страници).
-
Не поставяйте бутон "Последно" на всеки потребителски интерфейс, защото хората ще щракнат върху него от любопитство. Забележете, че Google има бутон „Напред“, но не и „Последен“. Така самият потребителски интерфейс обезкуражава хората да изпълняват неефективни заявки с големи отмествания.
-
Ако потребителят напредва една по страница, използвайте най-високата стойност на идентификатора, върната на предишната страница в клаузата WHERE на заявката на следващата страница. т.е. следното прави използвайте индекса, дори и без намек за FORCE INDEX:
SELECT * FROM thistable WHERE id > 544 LIMIT 20