如何计算与另一个表相关的行数

时间:2013-06-08 07:29:58

标签: mysql sql performance

我有两张桌子:

CATEGORY

category_id         int(10)          UNSIGNED  AUTO_INCREMENT
category_title      varchar(255)

产品

product_id          int(10)          UNSIGNED  AUTO_INCREMENT
product_category    int(10)          UNSIGNED 
product_title       varchar(255)

product_category是与category_id相关的外键。以下是一些数据:

category_id    category_title
-----------    --------------
          3    Cellphone
          4    Motherboard
          5    Monitor

product_id    product_category    product_title
----------    ----------------    -------------
         3    3                   Samsung Galaxy SIII
         4    3                   Apple iPhone 5
         5    3                   HTC One X

如何使用产品数量获取所有类别?

category_id    category_title    products_count
-----------    --------------    --------------
          3    Cellphone         3
          4    Motherboard       9
          5    Monitor           7

我使用了这个查询:

SELECT 
    `category_id` AS  `id`,
    `category_title` AS  `title`,
    COUNT(  `product_id` ) AS  `count` 

FROM  `ws_shop_category` 
    LEFT OUTER JOIN  `ws_shop_product`
        ON  `product_category` =  `category_id` 

GROUP BY  `category_id` 
ORDER BY  `title` ASC 

但这需要太长时间:(总共254次,查询耗时4.4019秒)。 如何更好地进行此查询?


DESC

在查询之前添加DESC,给我这个结果:

id  select_type table               type    possible_keys   key     key_len ref     rows    Extra
1   SIMPLE      ws_shop_category    ALL     NULL            NULL    NULL    NULL    255     Using temporary; Using filesort
1   SIMPLE      ws_shop_product     ALL     NULL            NULL    NULL    NULL    14320   

SHOW CREATE TABLE

CREATE TABLE `ws_shop_product` (
 `product_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `product_category` int(10) unsigned DEFAULT NULL,
 `product_title` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
 PRIMARY KEY (`product_id`)
) ENGINE=MyISAM AUTO_INCREMENT=14499 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

CREATE TABLE `ws_shop_category` (
 `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `category_title` varchar(255) COLLATE utf8_general_ci DEFAULT NULL,
 PRIMARY KEY (`category_id`)
) ENGINE=MyISAM AUTO_INCREMENT=260 DEFAULT CHARSET=utf8 COLLATE=utf8_general_ci;

3 个答案:

答案 0 :(得分:2)

您的表未定义任何索引。但是,通过使用以下statememts添加索引很容易解决:

ALTER TABLE `product` ADD INDEX `product_category` (`product_category`);
ALTER TABLE `category` ADD PRIMARY KEY(category_id);

现在,如果再次运行查询,DESC应该会显示查询使用密钥并且应该更快。

答案 1 :(得分:0)

SELECT ws_shop_category.*, count(ws_shop_product.product_category) as products_count        
from ws_shop_category
left join ws_shop_product
on (ws_shop_category.category_id = ws_shop_product.product_category)
group by
    ws_shop_category.category_id
order by  
    ws_shop_category.category_title asc 

答案 2 :(得分:0)

如果您需要高性能,我建议将类别中的产品数量存储为product_category的列或单独的表。您可以在每个产品插入/删除(手动或使用触发器)上更新相关计数器,也可以使用计划作业每隔N分钟更新所有计数器。

您可以在此处找到使用触发器的示例:Speeding up row counting in MySQL