Огромная разница в скорости в двух похожих запросах (предложение MySQL ORDER) - PullRequest
0 голосов
/ 02 декабря 2018

Важное обновление (объяснение): Я понял, что мой запрос с одним заказом DESC в 10 раз медленнее, чем тот же запрос с заказом ASC.Упорядоченное поле имеет индекс.Это нормальное поведение?

Оригинальный вопрос с запросами:

У меня есть таблица mysql с несколькими сотнями наименований товаров.Удивительно (для меня), как 2 одинаковых SQL-запроса отличаются с точки зрения производительности.Я не знаю почему.Можете ли вы дать мне подсказку или объяснить, почему разница настолько велика?

Этот запрос занимает 3 мс:

SELECT
    *
FROM
    `product_items`
WHERE
    (product_items.shop_active = 1)
    AND (product_items.active = 1)
    AND (product_items.active_category_id is not null)
    AND (has_picture is not null)
    AND (price_orig is not null)
    AND (category_min_discount IS NOT NULL)
    AND (product_items.slug is not null)
    AND `product_items`.`active_category_id` IN (6797, 5926, 5806, 6852)
ORDER BY
    price asc
LIMIT 1

Но следующий запрос занимаетуже 169 мс ... Разница лишь в том, что предложение order содержит 2 столбца.Значение «цена» присваивается каждому продукту, а «вершина цены» - примерно только 1% продуктов.

SELECT
    *
FROM
    `product_items`
WHERE
    (product_items.shop_active = 1)
    AND (product_items.active = 1)
    AND (product_items.active_category_id is not null)
    AND (has_picture is not null)
    AND (price_orig is not null)
    AND (category_min_discount IS NOT NULL)
    AND (product_items.slug is not null)
    AND `product_items`.`active_category_id` IN (6797, 5926, 5806, 6852)
ORDER BY
    price asc,
    price_top desc
LIMIT 1

Структура таблицы выглядит следующим образом:

CREATE TABLE `product_items` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `shop_id` int(11) DEFAULT NULL,
  `item_id` varchar(255) DEFAULT NULL,
  `productname` varchar(255) DEFAULT NULL,
  `description` text,
  `url` text,
  `url_hash` varchar(255) DEFAULT NULL,
  `img_url` text,
  `price` decimal(10,2) DEFAULT NULL,
  `price_orig` decimal(10,2) DEFAULT NULL,
  `discount` decimal(10,2) DEFAULT NULL,
  `discount_percent` decimal(10,2) DEFAULT NULL,
  `manufacturer` varchar(255) DEFAULT NULL,
  `delivery_date` varchar(255) DEFAULT NULL,
  `categorytext` text,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `active_category_id` int(11) DEFAULT NULL,
  `shop_active` int(11) DEFAULT NULL,
  `active` int(11) DEFAULT '0',
  `price_top` decimal(10,2) NOT NULL DEFAULT '0.00',
  `attention_priority` int(11) DEFAULT NULL,
  `attention_priority_over` int(11) DEFAULT NULL,
  `has_picture` varchar(255) DEFAULT NULL,
  `size` varchar(255) DEFAULT NULL,
  `category_min_discount` int(11) DEFAULT NULL,
  `slug` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `index_product_items_on_url_hash` (`url_hash`),
  KEY `index_product_items_on_shop_id` (`shop_id`),
  KEY `index_product_items_on_active_category_id` (`active_category_id`),
  KEY `index_product_items_on_productname` (`productname`),
  KEY `index_product_items_on_price` (`price`),
  KEY `index_product_items_on_discount_percent` (`discount_percent`),
  KEY `index_product_items_on_price_top` (`price_top`)
) ENGINE=InnoDB AUTO_INCREMENT=1715708 DEFAULT CHARSET=utf8;

ОБНОВЛЕНИЕ Я понял, что разница в основном в типе порядка: если я использую asc + asc для обоих столбцов, запрос занимает около 6 мсек, если я использую asc + desc или desc + asc, запрос занимает около 160 мс ..

Спасибо.

1 Ответ

0 голосов
/ 03 декабря 2018

Если создание индекса, чтобы помочь ORDER BY, не помогает, попробуйте создать индекс, который помогает WHERE и ORDER BY:

CREATE INDEX product_items_i1 ON product_items (
    shop_active,
    active,
    active_category_id,
    has_picture,
    price_orig,
    category_min_discount,
    slug,
    price,
    price_top DESC
)

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...