Mysql分页不止一个table

Mysql paginate more than one table

我在一个电子商务网站上工作,其中 MySQL 中有 2 个数据库 table,一个是产品,另一个是分类法,产品和分类法是多对多的关系,分类法具有树结构,这意味着分类法 table 中有一个 parent_id 字段来标识分类法的父 ID。

当用户选择一个分类时,我想获取属于该分类的所有产品及其所有后代分类,我是通过首先找出所选分类的所有后代分类,然后得到分页产品结果来实现的从那里开始,但在我的站点中总共有 5000 个分类法,我的解决方案使站点像狗一样慢......关于如何为了性能实现这一点有什么建议吗?

产品table:

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

分类法 table:

+--------------+------------------+------+-----+---------+----------------+
| 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 table:

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

如果单层深度可以使用下面的查询

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`

可以在上面的查询中加上limit,offset进行分页

上述查询中的

100表示用户请求的分类id。

除此之外我建议:-

1) 您的产品 table 中的 id 如有可能重命名为 product_id,如您的 product_taxonomy 和我假设在其他 table 中,类似地 taxonomy_id.

这样当你加入查询时列名会是一样的。

2) 我希望 product_taxonomy.product_id, product_taxonomy.taxonomy_id 被索引以便更快的查询。

更新:

您在下面的评论中提到的是分层数据问题,而不是关系数据库的理想用途。

解决方案 1

如果您确定每代只有 4 个级别,那么您可以执行 4 个连接查询。

如果需要,我可以详细说明。

解决方案 2

如果您对这个项目的架构不太了解或不感兴趣,我建议您以这种方式重构它,其中递归由服务器端脚本处理。也就是说,您以这样一种方式更改 CMS/taxonomy 管理,即每当您 add/remove/modify 分类法时,脚本都会更新一个名为 taxonomy_childs 的 table,其中包含给定类别的所有可能后代,以便您在您需要的时候有一个平面数据供您使用。

我个人更喜欢这个。我总是喜欢我的数据库符合我的业务逻辑要求。

如果需要,我可以详细说明。

解决方案 3

如前所述,分层数据不是关系数据库的强项。话虽如此,您可以实现称为嵌套集模型的东西。

请在 http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

阅读更多内容

您需要在分类法中添加 3 列 table :- level_depth, lft, rht。

请告诉我您希望我详细说明哪种解决方案。