我想按标签搜索对象。我想出的第一种方法是以下模型:
Object(OID, Tags, ...)
Tag(TagID, Name, ...)
ObjectTag(OID, TagId)
字段Tags
包含所有标记名称。
现在,我不仅希望通过一个标签搜索,而是通过许多标签搜索。查询看起来像这样:
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 = ?
我用大约100k个对象和每个对象5-20个标签测试了它,它花了大约30秒或更长时间,因此它经常超过PHP时间限制。
出于好奇,我还尝试使用LIKE
基于字段标记进行查询。
SELECT `o`.*
FROM object
WHERE object.tags LIKE '%tag1%' AND object.tags LIKE = '%tag2%' ...
但是,此查询在10秒内执行。不知怎的,我可以理解扫描一个表比交叉操作更快,但这样我就不能使用索引了。
我的目标是响应时间,不会吓跑用户。
答案 0 :(得分:1)
我假设您的索引针对第一个示例进行了优化。
而不是您的第一个查询具有所有这些连接,您是否尝试加入一次,然后确保每个记录都有该标记。请注意,HAVING
子句的N值取决于您要搜索的标记数。
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
您未提供具有预期结果集的任何样本数据。你也没有明确地显示SELECT
子句,所以这是最好的猜测。