如何在垂直设计的表格上实现搜索?

Nin*_*nse 2 mysql sql database

我有这样的表结构(垂直设计).我可以为每个用户提供无限数量的属性(例如:城市,电话等).

表:tbl_UserAttributes

???????????????????????????????????
| UserID ? FieldName ? Value      |
???????????????????????????????????
? 341    ? city      ? MyCity1    ?
? 772    ? phone     ? 1234567890 ?
? 033    ? city      ? MyCity2    ?
? 044    ? sex       ? M          ?
? 772    ? firstname ? MyName     ?
? ---    ? ---       ? ---        ?
???????????????????????????????????
Run Code Online (Sandbox Code Playgroud)

我必须实现一个搜索功能,它应该输出我们为水平设计的表应用查询的行:

SELECT 
    FieldName 
FROM 
    tbl_UserAttributes 
WHERE 
    city='%Mumbai%' AND 
    sex='M' AND ...
Run Code Online (Sandbox Code Playgroud)

请不要让我改变数据库设计.

更新:目前,我有一个JOIN解决方案,非常慢,它有时会挂起服务器.任何替代方法?

Qua*_*noi 7

EAV table是一件好事,只要你不需要一次搜索多个值,在这种情况下它会变得很糟糕.

您不能一次索引多个值,因为它们位于不同的记录中.

SQL Server表格中,您可以在多个值上创建索引视图,并将其用于搜索.

Oracle,您可以对表进行聚类,通过UserID该表将所有记录保持UserID在一个数据页中,该数据页将使用最具选择性值的索引并快速扫描其他值.

PostgreSQL,您可以将所有值存储在单个数组中,并使用索引对其进行GIN索引.

MySQL,你不能这样做.

这是一个返回值的查询:

SELECT  *
FROM    tbl_UserAttributes tcity
JOIN    tbl_UserAttributes tsex
ON      tsex.userid = tcity.userid
WHERE   tcity.fieldname = 'city'
        AND tcity.value LIKE '%Mumbai%'
        AND tsex.fieldname = 'sex'
        AND tsex.value = 'M'
Run Code Online (Sandbox Code Playgroud)

但不要指望它会非常快.

更新:

如果您需要具有完全匹配,则可以创建复合索引(fieldname, value, userid),将最具选择性fieldname放入第一个表并使用STRAIGHT_JOIN强制顺序:

SELECT  *
FROM    tbl_UserAttributes tcity
STRAIGHT_JOIN
        tbl_UserAttributes tsex
ON      tsex.userid = tcity.userid
WHERE   tcity.fieldname = 'city'
        AND tcity.value = 'Mumbai'
        AND tsex.fieldname = 'sex'
        AND tsex.value = 'M'
Run Code Online (Sandbox Code Playgroud)

但是,这对您当前的查询没有帮助,因为您正在寻找通配符匹配,在这种情况下索引不是很有帮助.除非您查询产科医院数据库,否则您的第二张表将不会从索引中受益.

由于可以使用索引扫描而不是表扫描,它仍然可以节省一些时间.