как оптимизировать запрос mysql: подсчет категории и подкатегории с помощью одного запроса из двух таблиц

мне нужна помощь для оптимизации этого запроса 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

хотя выше запрос возвращает ожидаемые результаты но я думаю, что может быть какой-то оптимизированный способ решить эту проблему. пожалуйста, направьте меня и предложите мне оптимизированный запрос.

спасибо

1 ответов


что такое производительность убийства-это filesort, вызванный одним из GROUP BYи/или UNION. Вы можете переписать запрос без UNION as:

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 показывает никаких filesort работа. Если это происходит, когда данные становятся больше, вы можете попробовать добавить ORDER BY NULL трюк.

также, если точность в реальном времени не очень важна, но запрос выполняется часто закешировать результат.