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。
请告诉我您希望我详细说明哪种解决方案。
我在一个电子商务网站上工作,其中 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。
请告诉我您希望我详细说明哪种解决方案。