我有一个要求如下。
create table bom_master (ID int NOT NULL AUTO_INCREMENT,label int, product varchar(20),PRIMARY KEY (ID));
插入陈述: -
insert into bom_master (label,product)values(1,'Budwieser');
insert into bom_master (label,product)values(2,'Heineken');
insert into bom_master (label,product)values(2,'Miller');
insert into bom_master (label,product)values(3,'Castle lite');
insert into bom_master (label,product)values(4,'Castle lager');
insert into bom_master (label,product)values(4,'Haywards');
insert into bom_master (label,product)values(3,'Kingfisher');
insert into bom_master (label,product)values(4,'Feni');
这是select语句输出。
mysql> select * from bom_master;
+----+-------+--------------+
| ID | label | product |
+----+-------+--------------+
| 1 | 1 | Budwieser |
| 2 | 2 | Heineken |
| 3 | 2 | Miller |
| 4 | 3 | Castle lite |
| 5 | 4 | Castle lager |
| 6 | 4 | Haywards |
| 7 | 3 | Kingfisher |
| 8 | 4 | Feni |
+----+-------+--------------+
8 rows in set (0.00 sec)
正如您所见,标签栏描绘了每种产品的标签。紧接着的下一个标签是前一个标签的子标签。 对于这里2是1的孩子,接下来的2是同一个孩子,然后3是2的孩子(3的前一个孩子)。然后4是3的孩子,接下来的4是3的孩子,然后3是以Miller为产品的2的孩子。接下来就是这样。
要实现这一点,这是我正在使用的select语句。但表现相当缓慢。对于10000条记录,需要6-7分钟才能获取。但50000条记录需要一个多小时。
mysql> select label_parent, label_child, product_parent, product_child
-> from (select t3.*,
-> @row_num := IF(@prev_value=t3.id_child,@row_num+1,1) as rn,
-> @prev_value := t3.id_child
-> from (select t1.label label_parent, t2.label label_child,
-> t1.product product_parent, t2.product product_child,
-> t1.id id_parent, t2.id id_child
-> from bom_master t1 join bom_master t2
-> on (t1.label = t2.label - 1 and t1.id < t2.id)) t3,
-> (select @row_num := 1) x,
-> (select @prev_value := '') y
-> order by t3.id_child, t3.id_parent desc) t4
-> where rn = 1
-> order by id_child;
+--------------+-------------+----------------+---------------+
| label_parent | label_child | product_parent | product_child |
+--------------+-------------+----------------+---------------+
| 1 | 2 | Budwieser | Heineken |
| 1 | 2 | Budwieser | Miller |
| 2 | 3 | Miller | Castle lite |
| 3 | 4 | Castle lite | Castle lager |
| 3 | 4 | Castle lite | Haywards |
| 2 | 3 | Miller | Kingfisher |
| 3 | 4 | Kingfisher | Feni |
+--------------+-------------+----------------+---------------+
我也试过索引。
create index bom_master_label_id_idx on bom_master (label, id);
如何改善表现?
答案 0 :(得分:0)
您可以通过以下方式更改label
逻辑 - 将label
更改为parentId(不是必需的,但不需要文档就可以更容易理解)。
因此parentId
将保留父项的ID
。例如,如果米勒是喜力啤酒的标签,喜力啤酒是百威啤酒的标签,你会有:
+----+-------+--------------+
| ID | parentId | product |
+----+-------+--------------+
| 1 | 0 | Budwieser |
| 2 | 1 | Heineken |
| 3 | 2 | Miller |
+----+-------+--------------+
拥有parentId = 0
意味着此产品没有任何父级。
因此,您不需要表格中产品顺序的复杂逻辑。
为了进一步优化,您可以添加额外的path
列,该列将保存每个子产品的父级路径。
例如:
+----+-------+--------------+--------------+
| ID | parentId | product | path |
+----+-------+--------------+--------------+
| 1 | 0 | Budwieser | |
| 2 | 1 | Heineken | |1| |
| 3 | 2 | Miller | |2|1| |
+----+-------+--------------+--------------+
|
- 是分隔符。但是当您path
或insert
产品时,此update
代码中需要一些逻辑。插入时,您必须获取当前产品的父路径,并使用父ID附加它。
如果您添加米勒,并且您为其父母选择了喜力,您将获得喜力的路径(|1|
)并附加2|
(喜力的ID)