Reputation: 4190
I want to search objects by tags. The first approach I came up with was the following model:
Object(OID, Tags, ...)
Tag(TagID, Name, ...)
ObjectTag(OID, TagId)
The field Tags
contains all tag names.
Now I don't only want to search by one tag but by many tags. The query looked like this:
SELECT `o`.*
FROM Object o
INNER JOIN ObjectTag tag1 ON(o.OID = tag1.OID)
INNER JOIN ObjectTag tag2 ON(o.OID = tag2.OID)
...
INNER JOIN ObjectTag tagn ON(o.OID = tagn.OID)
WHERE tag1.TagID = ? AND tag2.TagID = ? AND ... AND tagn.TagID = ?
I tested this with about 100k objects and 5-20 tags per object and it took about 30 seconds or more so it often exceeded the PHP time limit.
Out of curiosity I also tried to query based on the field tags using LIKE
.
SELECT `o`.*
FROM object
WHERE object.tags LIKE '%tag1%' AND object.tags LIKE = '%tag2%' ...
However, this query was executed in under 10 seconds. Somehow I can understand that scanning one table is faster than an intersect operation but that way I cannot use an index.
My aim is a response time which does not scare the users away.
Upvotes: 0
Views: 118
Reputation: 5271
I assume your indexes are optimized for the first example.
Instead of your first query having all of those joins, did you try to join once then make sure every record has that tag. Notice that the HAVING
clause's N value is based on the number of tags your are searching for.
SELECT object.keyfield, COUNT(*)
FROM object
JOIN objectTag
ON object.OID = objectTag.OID
WHERE objectTag.TagID IN (tag1,tag2,tag3...tagN)
GROUP BY object.keyfield
HAVING COUNT(*) >= N
You did not give any sample data with an expected result set. You also did not explicitly show the SELECT
clause so this is a best guess.
Upvotes: 1