Вопрос

Я работаю в интернет-магазине, который продает продукты только по кредитам. Я показываю 10 продуктов на страницу в любой категории, каждый продукт имеет 3 различных ценника - 3 различных типа кредита. Все прошло довольно хорошо во время тестирования, время выполнения запросов было совершенным, но сегодня при перенесении изменений на производственный сервер, сайт «рухнул» примерно в 2 минутах. Запрос, который используется для выбора типов кредитов, иногда висит в течение ~ 10 секунд, и это часто бывает часто и, таким образом, не может идти в ногу и его Hella Slow. Отказ Таблица, которая используется для хранения данных, имеет примерно 2 записи MILOION, и каждый выбор выглядит следующим образом:

SELECT * 
FROM products_loans 
WHERE KOD IN("X17/Q30-10", "X17/12", "X17/5-24") 
AND 369.27 BETWEEN CENA_OD AND CENA_DO;

3 Типы кредитов и цена, которая должна быть в пределах диапазона между Cena_OD и Cena_do, при этом возвращаются 3 ряда.

Но поскольку мне нужно отобразить 10 продуктов на странице, мне нужно запустить его через модифицированный выбор, используя ИЛИ, так как я не нашел никакого другого решения этого. Я спрашивал об этом здесь, но нет ответа. Как упоминалось в ссылке на пост, это должно быть сделано отдельно, так как есть нет Колонна, которая может быть использована в присоединении (кроме цена и кода конечно, но это закончилось очень очень плохо). Здесь show create table, kod и cena_od / cena_do очень проиндексированы по индексу.

CREATE TABLE `products_loans` (
  `KOEF_ID` bigint(20) NOT NULL,
  `KOD` varchar(30) NOT NULL,
  `AKONTACIA` int(11) NOT NULL,
  `POCET_SPLATOK` int(11) NOT NULL,
  `koeficient` decimal(10,2) NOT NULL default '0.00',
  `CENA_OD` decimal(10,2) default NULL,
  `CENA_DO` decimal(10,2) default NULL,
  `PREDAJNA_CENA` decimal(10,2) default NULL,
  `AKONTACIA_SUMA` decimal(10,2) default NULL,
  `TYP_VYHODY` varchar(4) default NULL,
  `stage` smallint(6) NOT NULL default '1',
 PRIMARY KEY  (`KOEF_ID`),
 KEY `CENA_OD` (`CENA_OD`),
 KEY `CENA_DO` (`CENA_DO`),
 KEY `KOD` (`KOD`),
 KEY `stage` (`stage`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

А также выбирая все типы кредитов, а позже фильтруют их кормушки PHP не работает хорошо, поскольку каждый тип имеет более 50 тысяч записей, и выбор также занимает слишком много времени ...

Любые идентификаторы о повышении скорости ценятся.

Редактировать:

Вот объяснение

+----+-------------+----------------+-------+---------------------+------+---------+------+--------+-------------+
| id | select_type | table          | type  | possible_keys       | key  | key_len | ref  | rows   | Extra       |
+----+-------------+----------------+-------+---------------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | products_loans | range | CENA_OD,CENA_DO,KOD | KOD  | 92      | NULL | 190158 | Using where |
+----+-------------+----------------+-------+---------------------+------+---------+------+--------+-------------+

Я попробовал комбинированный индекс, и он улучшил производительность на тестовом сервере от 0,44 ° до 0,06 сек, я не могу получить доступ к производственному серверу из дома, поэтому мне придется попробовать это завтра.

Это было полезно?

Решение

Попробуйте решить ваш запрос, как:

SELECT * FROM products_loans 
WHERE KOD IN("X17/Q30-10", "X17/12", "X17/5-24") 
AND CENA_OD >= 369.27
AND CENA_DO <= 369.27;

(MySQL не очень умный при выборе индексов) и проверьте производительность.

Следующая попытка - добавить комбинированный ключ - (ood, cena_od, cena_do)

А следующая крупная попытка - реформировать вашу базу, чтобы иметь продукты, разделенные от цен. Это должно действительно помочь.

PS: Вы также можете мигрировать в PostgreSQL, это умнее MySQL при выборе правильных индексов.

Другие советы

Ваша проблема заключается в том, что вы ищете интервалы, которые содержат точку (а не более нормальный запрос всех точек в интервале). Эти запросы не работают хорошо со стандартным индексом B-дерева, поэтому вместо этого вам нужно использовать индекс R-дерева. К сожалению MySQL не позволяет вам выбрать индекс R-дерева в столбце, но вы можете получить нужный индекс, изменив тип столбца в геометрию и используя геометрические функции для проверки, содержит ли интервал точка.

Видеть КвадраСтатья Список соседних против вложенных наборов: MySQL Где он объясняет это более подробно. Сейс использования отличается, но участвующие методики одинаковы. Вот экстракт из соответствующей части статьи:

Существует также определенный класс задач, которые требуют поиска всех диапазонов, содержащих известное значение:

  • В поисках IP-адреса в списке башен IP-диапазона
  • В поисках данной даты в пределах даты

и несколько других. Эти задачи могут быть улучшены с помощью возможностей R-деревьев MySQL.

MySQL может использовать только 1 ключ. Если вы всегда получаете запись на 3 столбцах, в зависимости от фактических данных (диапазон) в столбцах, одно из следующих, которые могут очень хорошо добавить серьезное количество производительности:

ALTER TABLE products_loans ADD INDEX(KOD, CENA_OD, CENA_DO);
ALTER TABLE products_loans ADD INDEX(CENA_OD, CENA_DO, KOD);

Обратите внимание, что порядок баллонов имеет значение! Если это не улучшает производительность, дайте нам EXPLAIN вывод запроса.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top