我有十个表(Product_A,Product_B,Product_C等),每个表都有一个主键指向父表Product中的一行。
基本上,我已经应用了来自Bill Karwin的SQL反模式书的建议(这里描述的反模式解决方案: https://fr.slideshare.net/billkarwin/practical-object-oriented-models-in-sql/34-Polymorphic_Assocations_Exclusive_Arcs_Referential)
为了加载儿童产品,我使用这样的东西:
SELECT * FROM Product
LEFT JOIN Product_A USING (product_id)
LEFT JOIN Product_B USING (product_id)
LEFT JOIN Product_C USING (product_id)
LEFT JOIN Product_D USING (product_id)
WHERE product_id = 1337
etc.
我担心我得到的子表产品类型越多,我必须添加的JOIN子句越多,导致查询结果非常慢。
如果我们处理数十个子子表,是否使用LEFT JOIN来防止多态关联反模式仍然是一个解决方案?
我是否应该开始考虑使用父表Product上的查询来获取" product_type"然后根据" product_type"中存储的值,在相应的子表上执行另一个查询;父表中的列?
更新:关于此主题的第一个回复说明这是糟糕的设计,我应该创建一个组合子表中的列的单个表。但每种产品类型都有自己的属性。换句话说:"电视可能有一个像素数,但这对于一个搅拌机来说没有多大意义。" @TomH
谢谢
答案 0 :(得分:3)
MySQL对连接数有严格的限制。限制是61个连接,并且它不可配置(我查看了源代码,它实际上只是硬编码)。因此,如果您有超过62种产品类型,则无法在单个查询中使用。
如果数据存储在您描述的结构中,我会针对每种产品类型运行单独的查询,因此您不会进行太多的连接。
或者首先对Product
表进行查询,如果需要详细信息,则对产品类型特定表进行其他查询。
例如,您何时需要同时收集产品特定的详细信息?在某种搜索页面上?您是否认为可以设计代码以仅显示搜索页面上主Product
表中的属性?
然后,只有当用户点击特定产品时,您才会转到其他页面以显示详细信息。或者如果不是一个不同的页面,也许它是一个动态HTML的东西,你扩展一个“+”按钮来获取详细信息,每次你这样做,运行一个AJAX请求的细节。
答案 1 :(得分:2)
是的,您可以使用product_type
(所谓的"鉴别器")来帮助DBMS生成更好的查询计划并避免不必要的连接。你可以这样做:
SELECT
*
FROM
Product
LEFT JOIN Product_A
ON product_type = 1 -- Or whatever is the actual value in your case.
AND Product.product_id = Product_A.product_id
LEFT JOIN Product_B
ON product_type = 2
AND Product.product_id = Product_B.product_id
LEFT JOIN Product_C
ON product_type = 3
AND Product.product_id = Product_C.product_id
LEFT JOIN Product_D
ON product_type = 4
AND Product.product_id = Product_D.product_id
WHERE
Product.product_id = 1337
DBMS应该能够短路所有分支"没有权利product_type
并避免相应的联接。 1
这实际上是否比使用单独的查询获取product_type
然后选择相应的"特殊"更好。查询(并产生另一个数据库往返) - 这是你应该测试的东西。与往常一样,测试代表性的数据量!
1 至少Oracle或SQL Server会这样做 - 请检查MySQL!
答案 2 :(得分:0)
这些表中会包含哪些数据?它只是关于产品的元数据吗?如果是这种情况,您可以创建一个描述每个产品的高桌。
例如,Product_Details表有三列:product_id,product_data_key,value。 product_data_key曾经是Product_A,Product_B,Product_C ......中的列...
您甚至可以拥有一个更好地描述product_data_key的单独表,因此它只是Product_Details中的外键。
答案 3 :(得分:0)
也许改变你的设计?一个产品可以具有许多属性(以及许多相同的属性),并且这些属性具有值。
我建议三个表:
Products ProductsAttributes Attributes
-Product_Id -Product_Id -Attribute_Id
-... -Attribute_Id -Attribute_Name
-Value -...
-...
使用原样:
SELECT p.Product_Id, a.Attribute_Name, pa.Value FROM Products p
JOIN ProductsAttributes pa ON pa.Product_Id = p.ProductId
JOIN Attributes a ON a.Attribute_Id = pa.Attribute_Id
然后,您可以重用属性,将它们绑定到产品,并存储它们的值。每个产品只具有所需的属性。