@arsenaljek

Как ускорить запрос SELECT который выводит цену в диапазоне дат?

Подскажите, как можно ускорить запрос
SELECT DATE_FORMAT(date,'%d.%m.%Y') as date1, `date`, `date` - INTERVAL 1 DAY AS `prevDate`, `price_product` FROM `prices` WHERE `id_product` = 235408123 ORDER BY `date`

Запрос выполняется секунд 13
Он выводит такие данные :
"date1" "date" "prevDate" "price_product"
"04.02.2019" "2019-02-04" "2019-02-03" "2870"
"07.02.2019" "2019-02-07" "2019-02-06" "2870"
"15.02.2019" "2019-02-15" "2019-02-14" "2857"
"23.02.2019" "2019-02-23" "2019-02-22" "2856"
"07.03.2019" "2019-03-07" "2019-03-06" "3359"
"08.03.2019" "2019-03-08" "2019-03-07" "3358"
"15.03.2019" "2019-03-15" "2019-03-14" "3356"
"16.03.2019" "2019-03-16" "2019-03-15" "3034"
"24.03.2019" "2019-03-24" "2019-03-23" "3036"
"29.03.2019" "2019-03-29" "2019-03-28" "3358"
"31.03.2019" "2019-03-31" "2019-03-30" "3356"
"01.04.2019" "2019-04-01" "2019-03-31" "3354"
"12.04.2019" "2019-04-12" "2019-04-11" "3348"
"13.04.2019" "2019-04-13" "2019-04-12" "3162"
"22.04.2019" "2019-04-22" "2019-04-21" "3156"
"30.04.2019" "2019-04-30" "2019-04-29" "3159"
"07.05.2019" "2019-05-07" "2019-05-06" "3162"
"24.05.2019" "2019-05-24" "2019-05-23" "2941"
"03.06.2019" "2019-06-03" "2019-06-02" "3162"

В таблице около 12 млн записей и они растут
Индексы стоят на id_product и date
CREATE TABLE `prices` (
	`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
	`id_product` VARCHAR(100) NOT NULL DEFAULT '0',
	`price_product` INT(11) NULL DEFAULT NULL,
	`date` DATE NULL DEFAULT NULL,
	PRIMARY KEY (`id`),
	INDEX `id_product` (`id_product`),
	INDEX `id_date` (`id_product`, `date`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=COMPACT

EXPLAIN возвращает такие данные
"id" "select_type" "table" "type" "possible_keys" "key" "key_len" "ref" "rows" "Extra"
"1" "SIMPLE" "prices" "ALL" "id_product,id_date" \N \N \N "13132125" "Using where; Using filesort"

Проблема именно в этом запросе, если его убрать, то страница открывается моментально.
  • Вопрос задан
  • 358 просмотров
Пригласить эксперта
Ответы на вопрос 3
@AUser0
Чем больше знаю, тем лучше понимаю, как мало знаю.
Ну заставьте MySQL перманентно использовать индекс:
SELECT DATE_FORMAT(date,'%d.%m.%Y') as date1, `date`, `date` - INTERVAL 1 DAY AS `prevDate`, `price_product` FROM `prices` FORCE INDEX (`id_product`) WHERE `id_product` = 235408123 ORDER BY `date`

Если версия MySQL не позволит выполнить такой запрос - поменяйте FORCE INDEX на USE INDEX.
Ответ написан
Stalker_RED
@Stalker_RED
Очень желательно id_product заменить на int, если это возможно, или перейти на использование того, другого id.

Попробуйте создать комбинированный индекс по всем полям участвующим в выборке. Он будет довольно большой и замедлит вставку, но улучшит выборку.

Попробуйте выбирать без сортировки, если разница будет очень большой, то можно делать ее отдельно. (подзапросом вытащить данные, и только потом сортировать).

Если все равно все плохо, и данные растут очень быстро, то возможно стоит рассмотреть другие БД, что-то высокопроизводительное, вроде tarantool, clickhouse или какие-то из семейства tsdb.
Ответ написан
Комментировать
Immortal_pony
@Immortal_pony Куратор тега MySQL
1. Судя по EXPLAIN, индексы у вас не используются при выполнении запроса. Это может происходить из-за того что индексы слишком большие и не лезут в память. Измените занчение innodb_buffer_pool_size (если у вас InnoDB) или key_buffer_size (если MyISAM) на ~30%-50% от оперативной памяти
2. Уберите сортировку из запроса если она вам нужна только для итоговой выборки. Воспользуйтесь конструкцией SELECT FROM SELECT чтобы отсортировать итоговую выборку
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы