我正在建立一个现在拥有数百万条记录的网站(道歉不能透露哪个网站)最初有几百条记录,所以下面的查询是可以接受的
查询: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 ...更像是一个问题然后解决方案
答案 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中的行与产品中的行进行匹配。
这是一个不完美的例子,但它得到了它的要点:
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 和类别中的现有条目