我有一個嵌套集模型的類別表。每一行應包含其子類別的數量,以及那些文章的數量,如果沒有,則爲'0'。MySQL嵌套設置子類別計算慢
我以防萬一搜查,發現了兩個可能的解決方案,但沒有他們的工作:
MySQL & nested set: slow JOIN (not using index)
Why isn't MySQL using any of these possible keys?
創建表格類別:
CREATE TABLE `categories` (
`GROUP_ID` varchar(255) CHARACTER SET utf8 NOT NULL,
`GROUP_NAME` varchar(255) CHARACTER SET utf8 NOT NULL,
`PARENT_ID` varchar(255) CHARACTER SET utf8 NOT NULL,
`TYPE` enum('root','node','leaf') CHARACTER SET utf8 NOT NULL DEFAULT 'node',
`LEVEL` tinyint(2) NOT NULL DEFAULT '0',
`GROUP_ORDER` int(11) NOT NULL,
`GROUP_DESCRIPTION` text CHARACTER SET utf8 NOT NULL,
`total_articles` int(11) unsigned NOT NULL DEFAULT '0',
`total_cats` int(11) unsigned NOT NULL DEFAULT '0',
`lft` smallint(5) unsigned NOT NULL DEFAULT '0',
`rgt` smallint(5) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`GROUP_ID`),
KEY `PARENT_ID` (`PARENT_ID`),
KEY `lft` (`lft`),
KEY `rgt` (`rgt`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
total_cats
是子類中的量行樹。
以下查詢將完全按照我的要求進行:所有子類別和文章數量。 但它很慢。在〜5000個類別和〜40000個文章上執行需要超過80秒的時間。total_articles
的計算已由另一個腳本完成。 (如果存在的arent任何物品,所有行應持有0
爲total_articles
)
查詢:
SELECT a.GROUP_ID,a.PARENT_ID,COUNT(b.GROUP_ID) as total_cats,(
SELECT SUM(c.total_articles)
FROM categories c
WHERE c.PARENT_ID = a.GROUP_ID) as total_articles
FROM categories as b
INNER JOIN categories as a
ON a.lft < b.lft AND a.rgt > b.rgt
GROUP BY a.GROUP_ID
它導致這樣的事情:
+-------------------------------------------+-------------------------------------+------------+----------------+
| GROUP_ID | PARENT_ID | total_cats | total_articles |
+-------------------------------------------+-------------------------------------+------------+----------------+
| 69_69_1 | 69_69_0 | 4252 | 0 |
| 69_69_Abfall__Wertstoffsammler___zubehoer | 69_69_NWEAB290h001 | 5 | 20 |
| 69_69_Abisolierzangen | 69_69_NWAAA458h001 | 4 | 56 |
| 69_69_Abzieher_2 | 69_69_NWAAB944h001 | 23 | 476 |
| 69_69_Abziehvorrichtung | 69_69_Abzieher_2 | 3 | 18 |
| 69_69_Aexte | 69_69_NWEAA615h001 | 6 | 45 |
| 69_69_Alarmgeraete_Melder | 69_69_Sicherungstechnik__Heimschutz | 3 | 4 |
| 69_69_Allgemeiner_Industriebedarf | 69_69_Industrieausruestung | 8 | 21 |
| 69_69_Allgemeines_Schweisszubehoer | 69_69_NWEAB113h001 | 27 | 97 |
| 69_69_Anker__Befestigungstechnik__1 | 69_69_Befestigungstechnik | 5 | 163 |
的解釋是否有幫助:
+----+--------------------+-------+------+---------------+-----------+---------+------+------+------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+------+---------------+-----------+---------+------+------+------------------------------------------------+
| 1 | PRIMARY | b | ALL | lft,rgt | NULL | NULL | NULL | 4253 | Using temporary; Using filesort |
| 1 | PRIMARY | a | ALL | lft,rgt | NULL | NULL | NULL | 4253 | Range checked for each record (index map: 0xC) |
| 2 | DEPENDENT SUBQUERY | c | ref | PARENT_ID | PARENT_ID | 767 | func | 7 | NULL |
+----+--------------------+-------+------+---------------+-----------+---------+------+------+------------------------------------------------+
正如你所看到的,它不使用索引。如果我把FORCE INDEX (lft,rgt)
放在JOIN
旁邊,查詢就會執行,但是沒有任何變化。還嘗試對列LFT和右添加索引:
ALTER TABLE `categories` ADD INDEX `nestedset` (`lft`, `rgt`);
但是,這並不幫助都沒有。查詢仍然很慢。
有趣的是:如果類別表剛剛填充少量行, 260.但是,如果它達到1000+以上,它會變得越來越慢。
具有〜4000類別的示例數據:http://pastebin.com/BsViwFM5其大文件!
感謝您的幫助和提示!
也許最好問dba.stackexchange? – davejal
也許你是對的,但其他人也會問類似的情況,所以如果有人想遷移它,隨時可以這樣做=) – UnskilledFreak
順便說一句,無論INT字出現在哪裏,它後面的數字都是毫無意義的 – Strawberry