我正在开发一个电子商务网站,其中MySQL有两个数据库表,一个是产品,另一个是分类,产品和分类是多对多关系,分类法有树结构,这意味着分类表中的parent_id字段,用于标识分类的父ID。
当用户选择一个分类法时,我希望获得属于该分类法及其所有后代分类法的所有产品,我首先找到所选分类法的所有后代分类法,然后从那里获得分页产品结果,但在我的网站上总共有5000种分类法,我的解决方案使网站变得像狗一样慢......有关如何为了性能而实现这一目标的任何建议吗?
产品表:
+-------------------+----------------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+----------------------+------+-----+---------------------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| code | bigint(20) | NO | UNI | NULL | |
| SKU | varchar(255) | NO | | NULL | |
| name | varchar(100) | NO | | NULL | |
| description | varchar(2000) | NO | | NULL | |
| short_description | varchar(200) | NO | | NULL | |
| price | decimal(8,2) | NO | | 0.00 | |
| discounted_price | decimal(8,2) | NO | | 0.00 | |
| stock | smallint(5) unsigned | NO | | 0 | |
| sales | smallint(5) unsigned | NO | | 0 | |
| num_reviews | smallint(6) | NO | | 0 | |
| weight | decimal(5,2) | NO | | 0.00 | |
| overall_rating | decimal(3,2) | NO | | 5.00 | |
| activity_id | int(10) unsigned | YES | MUL | NULL | |
| created_at | timestamp | NO | | 0000-00-00 00:00:00 | |
| updated_at | timestamp | NO | | 0000-00-00 00:00:00 | |
+-------------------+----------------------+------+-----+---------------------+----------------+
分类表:
+--------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| name | varchar(100) | YES | UNI | NULL | |
| parent_id | int(10) unsigned | YES | MUL | NULL | |
| num_products | smallint(6) | NO | | 0 | |
+--------------+------------------+------+-----+---------+----------------+
product_taxonomy表:
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| product_id | int(10) unsigned | NO | MUL | NULL | |
| taxonomy_id | int(10) unsigned | NO | MUL | NULL | |
+-------------+------------------+------+-----+---------+----------------+
答案 0 :(得分:1)
如果单级别的深度可以使用以下查询
SELECT * FROM `product_taxonomy`
INNER JOIN (SELECT * FROM `taxonomies` WHERE `id` = 100 OR `parent_id` = 100) `taxonomies`
ON `product_taxonomy`.`taxonomy_id` = `taxonomies`.`id`
LEFT JOIN `products` ON `product_taxonomy`.`product_id` = `products`.`id`
您可以将限制,偏移添加到上面的分页查询中。
上述查询中的100 表示用户请求的分类标识。
除此之外,我建议: -
1)产品表中的 id
,如果可能的话,会重命名为product_taxonomy中引用的product_id
,而我在其他表格中假设taxonomy_id
。
这种方式,当您加入查询列名称时将是相同的。
2)我希望product_taxonomy
。product_id
,product_taxonomy
。taxonomy_id
被编入索引,以便更快地进行查询。
<强>更新强>
您在下面的评论中提到的是分层数据问题,而不是理想情况下的关系数据库。
解决方案1
如果您确定您将只有4个级别/代,那么您可以进行4次加入查询。
如果需要,我可以详细说明。
解决方案2
如果你不太深入或致力于这个项目的体系结构,我建议重组它,这样一种方式,服务器端脚本处理递归。即,您更改CMS /分类法管理时,无论何时添加/删除/修改分类法,脚本都会更新一个名为taxonomy_childs
的表,其中包含给定类别的所有可能后代,以便您拥有平坦的数据。在需要时处理。
我个人更喜欢这个。我总是喜欢我的数据库来满足我的业务逻辑要求。
如果需要,我可以详细说明。
解决方案3
如前所述,分层数据不是关系数据库的强项。说过你可以实现一个叫做嵌套集模型的东西。
请在http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/
了解详情您需要在分类表中添加3列: - level_depth,lft,rht。
请让我知道您希望我详细说明哪种解决方案。