两个类似查询(MySQL ORDER子句)中的巨大速度差异

时间:2018-12-02 20:51:47

标签: mysql sql

重要更新(说明): 我意识到,具有单个DESC顺序的查询比具有ASC顺序的查询慢10倍。有序字段具有索引。这是正常行为吗?

带有查询的原始问题

我有一个带有数百个产品项的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

但是以下查询已花费169ms ... ,唯一的区别是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,则查询大约需要6ms;如果我使用asc + desc或desc + asc,则查询大约需要160ms。

谢谢。

1 个答案:

答案 0 :(得分:0)

如果创建索引对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
)

显然,这有点笨拙,您必须在查询的性能提升与维护索引的代价之间取得平衡。