I have a table structure like this (vertical design). I can have unlimited number of attributes (eg: city, phone etc.) for each user.
Table: tbl_UserAttributes
┌────────┬───────────┬────────────┐
| UserID │ FieldName │ Value |
├────────┼───────────┼────────────┤
│ 341 │ city │ MyCity1 │
│ 772 │ phone │ 1234567890 │
│ 033 │ city │ MyCity2 │
│ 044 │ sex │ M │
│ 772 │ firstname │ MyName │
│ --- │ --- │ --- │
└────────┴───────────┴────────────┘
I have to implement a search feature which should output rows which we apply query like this for a horizontally designed table:
SELECT
FieldName
FROM
tbl_UserAttributes
WHERE
city='%Mumbai%' AND
sex='M' AND ...
Please dont ask me to change the database design.
UPDATE: At present, I have a JOIN solution in place which is very slow and it hangs the server some times. Any alternate methods?
EAVtable is a good thing as long as you don’t need to search for multiple values at once in which case it becomes a bad thing.You cannot index several values at once because they are located in different records.
In an
SQL Servertable you could create an indexed view over multiple values and use it for the searches.In
Oracle, you could cluster the table byUserIDwhich would keep all records with the sameUserIDwithin one data page which would use an index on the most selective value and quickly scan for the other values.In
PostgreSQL, you could store all value in a single array and index it with aGINindex.In
MySQL, you can do neither of this.Here’s a query which will return the values:
but don’t expect it to be very fast.
Update:
If you needed to have the exact matching, you could create a composite index on
(fieldname, value, userid), put the most selectivefieldnameinto the first table and useSTRAIGHT_JOINto force the order:However, this won’t help with your current query, since you are looking for a wildcard match in which case the indexes are not very helpful. And your second table won’t benefit much from the index unless you are querying a maternity hospital database.
Still it will save you some time since the index scan can be used instead of a table scan.