admin

需要正确索引包含许多要搜索字段的表的建议

sql

我有一个包含许多列的用户表,它看起来大致像这样:

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;

由于用户可以选择要过滤的字段的任意组合,因此我不确定如何索引该表,我是否应该在所有可以过滤的字段上创建一个单列索引?您有什么建议?


阅读 192

收藏
2021-07-01

共1个答案

admin

我有一张工作在同一张桌子上的表,有很多列和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%。这将是非常不酷)

如果选择拆分表,还有更多事情需要考虑,例如如何将属性存储为数字,日期和文本在单个列中?还是这些单独的表或列。宽表或拆分表都不容易回答。

2021-07-01