Есть простая таблица:
CREATE TABLE test_table
(
id CHAR(36) NOT NULL PRIMARY KEY,
price INT DEFAULT '0' NOT NULL,
week_day INT NOT NULL,
hour INT NOT NULL,
minute INT NOT NULL,
is_active TINYINT(1) DEFAULT '0' NOT NULL
);
CREATE INDEX weekDay ON test_table (week_day);
CREATE INDEX test_index ON test_table (price, week_day, hour, minute);
делаю в нее запрос:
SELECT *
FROM test_table AS c2_
WHERE c2_.price > '0'
AND c2_.price < '100000000000'
AND c2_.week_day = '3'
AND (c2_.hour >= '10' AND c2_.minute >= '00')
AND (c2_.hour <= '22' AND c2_.minute <= '00')
Однако вижу, что используется индекс weekDay, а не по всем полям. Что я делаю не так?
Оптимизатор видит, что вы задали по price условие покрывающее собой всю БД, следовательно для его проверки ему придется просканировать весь индекс целиком, что не рационально, поэтому он отказывается его использовать. вот если бы по price был бы небольшой диапазон и оптимизатор это бы понял, то он бы вполне мог использовать индекс.
Вообще в индексе на первое место стоит ставить поля, поиск по которым идет на точное равенство. А поля, по которым поиск идет по диапазону должны быть последними при объявлении индекса.
Фактически любые индексы, по которым предполагается поиск по диапазону значений более чем по одному полю, малоэффективны. Потому как при сканировании диапазона по первому полю надо будет прыжками идти по кусочкам отвечающим за нужные значения второго поля. Но все равно придется пройти весь участок по первому полю.
Сборка персонального компьютера от Artline: умный выбор для современных пользователей