MySQL:具有多个类别的产品的SQL和DB

时间:2013-07-24 23:14:57

标签: php mysql database

我正在建立一个现在拥有数百万条记录的网站(道歉不能透露哪个网站)最初有几百条记录,所以下面的查询是可以接受的

查询:SELECT * FROM ... .WHERE类别LIKE'%,3,%';

但现在它只是为每个查询杀死数据库,它必须通过上述查询遍历整个2Mil记录

类别表
ID NAME
1女 2时尚
3服装
4配件
5顶部 6连衣裙
7耳环
8短礼服
9长礼服
10男

产品表
ID ... ..Category ...。其他位
1,1,2,3,6,9,......
2,1,2,4,7,
3,1,2,3,5,
4,10,2,3,4,

你有上面发生的事情。现在如果我在产品表中的类别行上执行FullText索引,它只提供1个基数:(

我怎样才能克服这一点? 我已经考虑过每个类别的重复行,但数据库目前是2 GIG并且重复数据库它将大约10 GIG ...更像是一个问题然后解决方案

3 个答案:

答案 0 :(得分:2)

请记住,将数字存储为字符串所需的字节数是将数字存储为整数的两倍。加上所有这些逗号。

因此,如果您担心空间问题,那么扩展将不会像您担心以规范化方式存储数据那样多。

它将允许您编写利用索引的正确查询。因此,如果有一些扩展,您将交换一点存储空间,以便大大提高速度。

提示:如果您使用的是InnoDB,则主键不会占用任何存储空间,因为表本身存储为主键索引。如果您需要按类别优化搜索,则应首先使用类别ID定义规范化表格,然后选择产品ID第二。

CREATE TABLE CategoryProduct (
  categoryid INT,
  productid INT,
  PRIMARY KEY (categoryid, productid)
);

另请参阅我对Is storing a delimited list in a database column really that bad?的回答,了解使用逗号分隔列表的更多缺点。

答案 1 :(得分:1)

我会考虑一个新表,比如说Product_Category(我知道是缺乏想象力的),其中每一行包含一个与Product.id的外键(FK)关系列和一个列的列。< / p>

category列可能是TINYINT,只需要1个字节来存储,而我猜FK列与Product.id列相同(可能是INT - 4个字节),然后您可以索引两列,以便您可以找出产品属于哪些类别以及哪些产品属于某个类别。此外,此表格不需要Primary Key(即id),为您节省额外的4个字节。

(见MySQL Data Type Storage Requirements

使用此解决方案,此新数据库中的每一行将占用大约5个字节。由于sting中的每个字符占用1个字节(假设ASCII和latin1编码),您将通过删除Product.category并将项目放入{{Product_Category来查看每个产品每个类别增加3个字节(包括逗号)。 1}}然而,这并不像复制整个产品行那样大。但是,更改代码需要付费(除非你比我joins好得多)。

这对你有帮助吗?

答案 2 :(得分:0)

我见过的一个解决方案是使用三个表:

  • 类别列出了您的类别
  • 产品列出您的产品,没有任何附加的类别信息
  • category_map 是一个特殊的表:每行将product_id链接到category_id

要按类别查找产品,您可以将category_map中的行与产品中的行进行匹配。

这是一个不完美的例子,但它得到了它的要点:

SELECT * FROM 
(
    SELECT * FROM category_map 
    WHERE category_id=1
) AS map 
INNER JOIN products 
ON products.id = map.product_id;

表连接是一个非常强大的工具;如果您不熟悉它们,可能需要花些时间阅读它们。 Coding Horror has a visual explanation that skims over the details

最好设置外键约束或以其他方式确保 category_map 中的条目对应 products 类别中的现有条目