以下是方案1。
我有一个名为“items”的表,表中有2列,e。 G。 item_id
和item_name
。
我以这种方式存储我的数据:
item_id | ITEM_NAME
Ss001 | Shirt1
Sb002 | Shirt2
Tb001 | TShirt1
Tm002 | TShirt2
...等,我这样存储: 第一个字母是衣服的代码,即S代表衬衫,T代表T恤 第二个字母是大小,即s代表小,m代表中等,b代表大 让我们在我的项目表中说我有10,000件物品。我想做快速检索,假设我想找一件特定的衬衫,我可以使用:
方法一:
SELECT * from items WHERE item_id LIKE Sb99;
或者我应该这样做:
方法2:
SELECT * from items WHERE item_id LIKE S*;
*存储结果,然后执行第二次搜索大小,然后第三次搜索id。像哈希表概念。 我想要实现的是,我想通过首先搜索衣服代码,然后按照大小代码然后是id代码来搜索所有数据,而不是搜索所有数据。在mysql中哪一个在速度方面更好。从长远来看哪一个更好。我想减少流量而不是经常打扰数据库。
感谢大家解决我的第一个场景。但另一种情况出现了:
情景2:
我正在使用PHP和MySQL。继续从早期的故事。如果我的用户表结构是这样的:
user_id | username | items_collected
U0001 | Alex | Ss001;Tm002
U0002 | Daniel | Tb001;Sb002
U0003 | Michael | ...
U0004 | Thomas | ...
我将items_collected存储在id格式中,因为有一天每个用户最多可以收集数百个项目,如果我存储为字符串,即Shirt1,pants2,......,则需要非常大量的数据库空间(想象一下)我们有1000个用户,有些项目名称很长。)
如果以id格式存储,维护会更容易吗?
如果我们说,我想显示图像,图像的名称是项目的名称+ jpg。怎么做?它是这样的:
$ result =从userid = $ userid
的用户中选择items_collected使用php explode:
$ itemsCollected = explode($ result,“;”);
之后,匹配items表中的每个项目,所以它希望:
shirt1,pants2等
使用循环功能,循环每个值并添加“.jpg”以显示图像?
答案 0 :(得分:3)
第一种方法会更快 - 但IMO并不是正确的做法。我同意tehvan的意见。
我建议保持item_id不变,但是为代码添加一个额外的字段,为大小添加一个,然后你可以这样做:
select * from items where item_code = 'S' and item_size = 'm'
使用索引可以大大提高性能,并且您可以轻松匹配各种尺寸或代码。
select * from items where item_code = 'S' and item_size IN ('m','s')
按如下方式迁移数据库:
alter table items add column item_code varchar(1) default '';
alter table items add column item_size varchar(1) default '';
update items set item_code = SUBSTRING(item_id, 1, 1);
update items set item_size = SUBSTRING(item_id, 2, 1);
对代码的更改应该同样易于添加。长期利益将是值得的。
对于方案2 - 这不是从数据库存储和检索数据的有效方法。当以这种方式使用时,数据库仅充当存储引擎,通过将多个数据编码到字段中,从而阻止数据库的关系部分变得有用。
在这种情况下你应该做的是另一张桌子,称之为'items_collected'。架构将沿着
的方向CREATE TABLE items_collected (
id int(11) NOT NULL auto_increment KEY,
userid int(11) NOT NULL,
item_code varchar(10) NOT NULL,
FOREIGN KEY (`userid`) REFERENCES `user`(`id`),
FOREIGN KEY (`itemcode`) REFERENCES `items`(`item_code`)
);
外键确保有Referential integrity,这是必不可少的to have referential integrity。
然后,对于您给出的示例,您将拥有多条记录。
user_id | username | items_collected
U0001 | Alex | Ss001
U0001 | Alex | Tm002
U0002 | Daniel | Sb002
U0002 | Daniel | Tb001
U0003 | Michael | ...
U0004 | Thomas | ...
答案 1 :(得分:1)
第一个优化是将id分成三个不同的字段: 一个用于类型,一个用于大小,一个用于当前id结尾(无论结束意味着什么) 如果您真的想保留当前结构,请立即查看结果(选项1)。
答案 2 :(得分:1)
如果您想加快结果速度,您应该将列拆分为多个列,每个属性对应一列。
第2步是为每列创建索引。请记住,mysql每个查询每个表只使用一个索引。因此,如果您真的想要快速查询,并且您的查询对这些属性的影响很大,那么您可能希望在(类型,大小,结尾),(类型,结尾,大小)等上创建索引。
例如使用
的查询select * from items where type = s and size = s and ending = 001
可以从索引(类型,大小,结尾)中受益,但是:
select * from items where size = s and ending = 001
不能,因为索引只会按顺序使用,所以它需要类型,然后是大小,然后结束。如果您真的想要快速搜索,这就是您可能需要多个索引的原因。
另一个注意事项,通常在查询中使用*不是一个好主意,而是只选择您需要的列。
答案 3 :(得分:1)
model
,size
和id
需要有三列,并以这种方式对其进行索引:
CREATE INDEX ix_1 ON (model, size, id)
CREATE INDEX ix_2 ON (size, id)
CREATE INDEX ix_3 ON (id, model)
然后,您将能够有效地搜索任何参数子集:
model-size-id
,model-size
和model
查询将使用ix_1
; size-id
和size
查询将使用ix_2
; model-id
和id
查询将使用ix_3
列上的索引现在等同于ix_1
,您可以使用此索引有效搜索适当的条件(model-size-id
,model-size
和{{1} })。
实际上,有一个名为model
的访问路径可用于搜索复合索引的非第一列,但INDEX SKIN SCAN
不支持它AFAIK。
如果您需要坚持当前的设计,则需要索引字段并使用以下查询:
MySQL
所有这些查询都将使用索引(如果有)。
无需插入多个查询。
答案 4 :(得分:0)
我很高兴您将item_id设计为可以通过“Starts with”测试进行搜索。索引将为您快速解决。
我不知道MySQL,但是在MSSQL上有一个“大小”列的索引只有S,M,L的选择最有可能无法实现任何东西,索引将不会被使用,因为值它包含的选择性不够 - 即更快地遍历所有数据而不是“在索引中查找第一个S条目,现在检索该行的数据页面......”
异常是索引覆盖查询的地方 - 即WHERE子句的几个部分(实际上,所有这些部分以及SELECT列)都包含在索引中。但是,在这种情况下,索引中的第一个字段(在MSSQL中)需要是选择性的。因此,在索引中首先放置具有最不同值的列。
如果您的应用程序有大小,颜色等的选项列表,您应该将这些数据属性放在记录中的单独列中 - 并将单独的表与所有可用颜色和大小的列表相对应,然后您可以验证给予产品的颜色/尺寸实际上是在颜色/尺寸表中定义的。减少垃圾进/出垃圾问题!
您的item_selected需要位于单独的表中,以便“标准化”。不要将分隔列表存储在单个列中,使用单独的表将其存储在单独的表中
因此,您的USERS表将包含user_id&用户名
您的新的items_collected表将包含user_id& item_id(可能还包括购买日期或发票编号)
然后你可以说“Alex买了什么”(你的设计有那个)以及“谁买了Ss001”(在你的设计中,需要翻阅USERS表中的所有行并将items_collected分割为找出哪些包含Ss001 [1])
[1]请注意,使用LIKE实际上并不安全,因为你可能有一个“Ss001XXX”的item_id,它匹配WHERE items_collected LIKE'%Ss001%'