8

我需要帮助来优化这个 MySQL 查询以获得更好和更快的性能。

这是SQL FIDDLE带有查询和表结构的。

基本上我有两张桌子

tbl_category

CREATE TABLE IF NOT EXISTS `tbl_category` (
  `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `category_name` varchar(20) NOT NULL,
  `parent_category_id` int(10) unsigned DEFAULT NULL,      
  PRIMARY KEY (`category_id`),
  UNIQUE KEY `category_name` (`category_name`,`parent_category_id`),
  KEY `category_parent_id` (`parent_category_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

--
-- data for table `tbl_auction`
-- 
+-------------+---------------+--------------------+-----------------+
| category_id | category_name | parent_category_id | category_status | 
+-------------+---------------+--------------------+-----------------+
|           1 | Boats         |               NULL | a               | 
|           2 | Books         |               NULL | a               | 
|           3 | Building      |               NULL | a               | 
|           4 | Cars          |               NULL | a               | 
|           5 | Electrical    |                  3 | a               | 
|           6 | Hardware      |                  3 | a               | 
|           7 | Heating       |                  3 | a               | 
|           8 | Miscellaneous |                  3 | a               | 
|           9 | Plumbing      |                  3 | a               | 
|          10 | Tools         |                  4 | a               | 
|          11 | Lights        |                  4 | a               | 
|          12 | Miscellaneous |                  4 | a               | 
+-------------+---------------+--------------------+-----------------+

tbl_auction

CREATE TABLE IF NOT EXISTS `tbl_auction` (
  `auction_id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
  `auction_category` int(10) unsigned NOT NULL 
   COMMENT 'either store subcategory OR main category if no subcategory',
  `auction_title` varchar(100) NOT NULL,     
  PRIMARY KEY (`auction_id`),
  KEY `auction_category` (`auction_category`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

--
-- data for table `tbl_auction`
--

+------------+------------------+---------------+
| auction_id | auction_category | auction_title | 
+------------+------------------+---------------+-
|          1 |                1 | one           | 
|          2 |                2 | two           | 
|          3 |                5 | five          | 
|          4 |                6 | six           | 
|          5 |                5 | five2         | 
|          6 |                8 | eight         | 
|          7 |               11 | eleven        | 
|          8 |               11 | eleven2       | 
|          9 |               10 | ten           | 
|         10 |                2 | two2          | 
|         11 |               12 | twelve        | 
+------------+------------------+---------------+

现在我想明智地计算所有拍卖类别,以及如果某个类别有子类别,那么将该拍卖与主类别相加

我做了以下查询

SELECT auction_category AS categoryID, COUNT(*) AS total
      FROM `tbl_auction`
      GROUP BY auction_category
UNION ALL
SELECT parent_category_id  AS categoryID, COUNT( * ) AS total
      FROM  `tbl_auction` ta
      INNER JOIN tbl_category tc ON tc.category_id = ta.auction_category
      WHERE parent_category_id IS NOT NULL
      GROUP BY parent_category_id

虽然上面的查询返回了预期的结果,但我认为可能有一些优化的方法来解决这个问题。请指导我并建议我优化查询。

谢谢

4

1 回答 1

3

扼杀性能的是由GROUP BYs 和/或UNION. 您可以重写查询而不UNION使用:

SELECT pcat.category_id, COUNT(*)
  FROM  tbl_category pcat
  LEFT JOIN tbl_category subcat 
    ON subcat.parent_category_id = pcat.category_id 
  INNER JOIN tbl_auction a 
    ON a.auction_category = IFNULL(subcat.category_id,pcat.category_id)
GROUP BY pcat.category_id;

这具有相同的效果(重复计算每次拍卖,一次在其子猫下,一次在父猫下),并且EXPLAIN显示没有文件排序。如果数据变大时确实如此,您可以尝试添加ORDER BY NULL技巧。

此外,如果实时准确性不是非常重要但查询经常执行,请考虑缓存结果。

于 2012-07-17T16:39:34.117 回答