我有一个包含许多列的用户表,它看起来大致像这样:
dname: { type: string(255), notnull: true } email: { type: string(255), notnull: true, unique: true } email_code: { type: string(255) } email_confirmed: { type: boolean, default: false } profile_filled: { type: boolean, default: false } password: { type: string(255), notnull: true } image_id: { type: integer } gender: { type: enum, values: [male, female] } description: { type: string } dob: { type: date } height: { type: integer(3) } looks: { type: enum, values: [thin, average, athletic, heavy] } looking_for: { type: enum, values: [marriage, dating, friends] } looking_for_age1: { type: integer } looking_for_age2: { type: integer } color_hair: { type: enum, values: [black, brown, blond, red] } color_eyes: { type: enum, values: [black, brown, blue, green, grey] } marital_status: { type: enum, values: [single, married, divorced, widowed] } smokes: { type: enum, values: [no, yes, sometimes] } drinks: { type: enum, values: [no, yes, sometimes] } has_children: { type: enum, values: [no, yes] } wants_children: { type: enum, values: [no, yes] } education: { type: enum, values: [school, college, university, masters, phd] } occupation: { type: enum, values: [no, yes] } country_id: { type: integer } city_id: { type: integer } lastlogin_at: { type: timestamp } deleted_at: { type: timestamp }
我创建了一个包含大多数字段(枚举,国家/地区,城市)的表单,该表单使用户能够根据他们选择的字段生成一个where语句。因此,如果有人选择抽烟:否和country_id:7,则sql where语句可能如下所示:
SELECT id FROM user u WHERE u.deleted_t IS NULL AND u.profile_filled IS NOT NULL AND smokes = 'no' AND country_id = 7;
由于用户可以选择要过滤的字段的任意组合,因此我不确定如何索引该表,我是否应该在所有可以过滤的字段上创建一个单列索引?您有什么建议?
我有一张工作在同一张桌子上的表,有很多列和1000种不同的选择方式。这是一场噩梦。但是,我确实发现,经常使用某些过滤器组合。我将为那些索引创建索引,而其他索引则很少用于缓慢运行。在MSSQL中,我可以运行查询以向我展示针对数据库运行的最昂贵的查询,mySQL应该具有类似的功能。有了它们之后,我将创建一个索引,该索引覆盖各列以加快它们的速度。最终,您将获得90%的覆盖率。我个人永远也不会再设计像这样的桌子,除非我有一个AK47指向我。(我的索引比表中的数据大3倍,如果您需要添加一堆或记录,这是非常不酷的)。我不确定我该如何重新设计桌子,
用户表(用户ID,名称)
1, Lisa 2, Jane 3, John
用户属性表(UserID,AttributeName,AttributeValue)
1, EYES, Brown 1, GENDER, Female 2, EYES, Blue 2, GENDER, Female 3 EYES, Blue 3, GENDER, Male
这样可以更快地识别属性,但使查询不那么容易编写。
SELECT UserID, COUNT(*) as MatchingAttributes FROM UserAttributes WHERE (UserAttributes.AttributeName = 'EYES' AND UserAttributes.AttributeValue = 'Blue') OR (UserAttributes.AttributeName = 'GENDER' AND UserAttributes.AttributeValue = 'Female')
这应该返回以下内容
UserID, MatchingAttributes 1, 1 2, 2 3, 1
然后,您需要做的就是向查询添加HAVING COUNT(*)= 2以仅选择匹配的ID。可以从中进行选择,但是它还提供了一个简洁的功能,例如您对10个属性进行过滤,并返回所有具有10个匹配项的属性。很酷,但说没有一个100%符合。您可能会说,我没有找到匹配的,但这些匹配有10个匹配中的9个或90%匹配。(请确保,如果我搜索一只蓝眼睛的金发女性,我不会收到一条消息,说找不到任何信息,但以下是最接近的匹配项,其中包含蓝眼睛的金发女郎,其匹配分数为60%。这将是非常不酷)
如果选择拆分表,还有更多事情需要考虑,例如如何将属性存储为数字,日期和文本在单个列中?还是这些单独的表或列。宽表或拆分表都不容易回答。