MySQL:选择任何给定类别的产品

时间:2015-03-19 15:38:07

标签: mysql join

我试图提高查询中的效果,该查询涉及获取属于任何类别列表的所有产品:

CREATE TABLE `shop_products` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `slug` varchar(125) NOT NULL,
  `on_sale` tinyint(3) unsigned NOT NULL,
  `deleted` tinyint(4) DEFAULT NULL,
  `created_date` datetime DEFAULT NULL,
  `updated_date` datetime DEFAULT NULL
  PRIMARY KEY (`id`),
  KEY `created_date` (`created_date`),
  KEY `slug` (`slug`),
  KEY `updated_date` (`updated_date`),
  KEY `on_sale_deleted` (`on_sale`,`deleted`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


CREATE TABLE `shop_product_terms` (
  `product_id` bigint(20) NOT NULL,
  `term_id` int(11) NOT NULL,
  KEY `term_id` (`term_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

选择属于任何给定类别列表的产品(未删除和销售):

SELECT p.id
FROM shop_products AS p
INNER JOIN shop_product_terms AS pt ON p.id=pt.product_id
WHERE
(pt.term_id=93 OR pt.term_id=97) AND 
p.on_sale=1 AND p.deleted IS NULL 
ORDER BY created_date DESC, updated_date DESC LIMIT 55, 10

目前执行时间为0.1秒。致电EXPLAIN

id  select_type table  partitions   type    possible_keys   key     key_len    ref                  rows   Extra
-----------------------------------------------------------------------------------------------------------------
1   SIMPLE      pt      NULL        range   term_id         term_id     4       NULL                362     Using where; Using temporary; Using filesort
1   SIMPLE      p       NULL        eq_ref  PRIMARY,on_sale PRIMARY     8       pt.product_id     1       Using where

我注意到(pt.term_id=93 OR pt.term_id=97)部分正在减缓查询速度(因为OR我猜测,因为类型=范围)。

有什么方法可以重写这个查询来改进这里的东西吗?


编辑:@Alex

提出的替代查询的EXPLAIN结果
id  select_type     table               partitions  type        possible_keys           key?    key_len?    ref?            rows?   Extra?
1   PRIMARY         <derived2>          NULL        ALL         NULL                    NULL    NULL        NULL            363     Using temporary; Using filesort
1   PRIMARY         p                   NULL        eq_ref      PRIMARY,on_sale_deleted PRIMARY 8           pt.product_id   1       Using where
2   DERIVED         shop_product_terms  NULL        range       term_id                 term_id 4           NULL            362     Using where

第二次编辑:

id  select_type         table               partitions          type    possible_keys       key?            key_len?    ref?            rows?   Extra?
1   PRIMARY             p                   NULL                ref     on_sale_deleted     on_sale_deleted 3           const,const     3502    Using where; Using filesort
2   DEPENDENT SUBQUERY  shop_product_terms  NULL                range   term_id             term_id         4           NULL            362     Using where

2 个答案:

答案 0 :(得分:0)

你要检查这是否真的更快。

SELECT p.id
FROM shop_products AS p
INNER JOIN shop_product_terms AS pt ON p.id=pt.product_id
WHERE
pt.term_id IN (93, 97) AND 
p.on_sale=1 AND p.deleted IS NULL 
ORDER BY created_date DESC, updated_date DESC LIMIT 55, 10

答案 1 :(得分:0)

只是为了提高性能,你可以:

SELECT p.id
FROM shop_products as p
INNER JOIN 
  (SELECT
     product_id
   FROM
     shop_product_terms 
   WHERE term_id IN (93,97)
) AS pt 
ON p.id=pt.product_id
WHERE
p.on_sale=1 AND p.deleted IS NULL 
ORDER BY created_date DESC, updated_date DESC LIMIT 55, 10

编辑,因为您为我发布了解释声明,我们可以尝试这种方式:

SELECT p.id
FROM shop_products AS p
WHERE
p.id IN (SELECT 
     product_id
   FROM
     shop_product_terms 
   WHERE term_id IN (93,97)
)
AND 
p.on_sale=1 AND p.deleted IS NULL 
ORDER BY created_date DESC, updated_date DESC LIMIT 55, 10