在Mysql

时间:2016-10-26 20:04:45

标签: mysql

我有一个要求如下。

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);

如何改善表现?

1 个答案:

答案 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|        |
+----+-------+--------------+--------------+

| - 是分隔符。但是当您pathinsert产品时,此update代码中需要一些逻辑。插入时,您必须获取当前产品的父路径,并使用父ID附加它。

如果您添加米勒,并且您为其父母选择了喜力,您将获得喜力的路径(|1|)并附加2|(喜力的ID)