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解决方案,非常慢,它有时会挂起服务器.任何替代方法?
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)
但是,这对您当前的查询没有帮助,因为您正在寻找通配符匹配,在这种情况下索引不是很有帮助.除非您查询产科医院数据库,否则您的第二张表将不会从索引中受益.
由于可以使用索引扫描而不是表扫描,它仍然可以节省一些时间.