8

この MySQL クエリを最適化して、パフォーマンスを向上させ、高速化するには、助けが必要です。

これはSQL FIDDLEwith Query と table 構造です。

基本的に私は2つのテーブルを持っています

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 BYおよび/または のいずれかによってトリガーされるファイルソートUNIONです。asなしでクエリを書き直すことができます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;

これには同じ効果があり (各オークションをそのサブ猫の下で 1 回、親猫の下で 1 回二重にカウントする)、ファイルソートはEXPLAIN表示されません。データが大きくなったときにそうなる場合は、ORDER BY NULLトリックを追加してみてください。

また、リアルタイムの精度はそれほど重要ではないが、クエリが頻繁に実行される場合は、結果をキャッシュすることを検討してください。

于 2012-07-17T16:39:34.117 に答える