如何使用多个标签快速搜索帖子/列表?

时间:2018-09-10 15:40:59

标签: php mysql innodb

我的目录网站当前使用"toxi" table structure标记列表。

我的posts表具有大约500万条记录,而map表具有大约1500万条记录。

我使用术语来存储各种信息,例如作者,出版者,主题,媒体(例如音频,视频等)。一个帖子可以为每个分类法使用多个术语(多个作者,多个主题等)。

基于单个term_id搜索帖子大约需要四秒钟才能返回结果,这很糟糕,但是使用多个术语返回结果需要40秒。

我需要一个更有效的解决方案,但我无法弄清楚是效率低下的查询还是表结构。

==单个搜索查询==

SELECT * FROM posts
LEFT JOIN post_taxonomy_term_map ON (posts.ID = post_taxonomy_term_map.object_id)
WHERE post_taxonomy_term_map.term_id=$term1

==多个术语查询==

SELECT p.*
FROM post_taxonomy_term_map m, posts p
WHERE m.term_id IN ($term1, $term2, $term3)
AND p.ID = m.object_id
GROUP BY p.ID
HAVING COUNT( p.ID )=3

表格和列

帖子 {ID,post_title等...}

主要ID

taxonomy_terms {term_id,term_label,term_slug等}

PRIMARY term_id

post_taxonomy_term_map {map_id,object_id,分类法,term_id}

PRIMARY map_id

INDEX object_id

INDEX term_id

索引分类

注意:post_taxonomy_term_map.object_id与posts.ID值有关

2 个答案:

答案 0 :(得分:1)

对于您的第一个查询:

SELECT *
FROM posts
LEFT JOIN post_taxonomy_term_map
    ON posts.ID = post_taxonomy_term_map.object_id
WHERE post_taxonomy_term_map.term_id = $term1

(term_id, object_id)上的复合索引。该索引包括一个或您的索引已经在做的term_id,但是它也通过包含object_id来覆盖联接。假设优化器认为WHERE子句具有足够的限制性以使用索引,那么它的性能应比您目前拥有的更好。

CREATE INDEX some_idx ON post_taxonomy_term_map(term_id, object_id);

答案 1 :(得分:0)

主要的性能问题可能是由于TOXI要求的many:many表。可以消除它:

CREATE TABLE Tags (
    tag VARHAR(...) NOT NULL,
    bid INT ... NOT NULL,
    PRIMARY KEY(tag, bid),
    INDEX(bid, tag)
)

注意:

  • 这比TOXI更好,因为它没有经过额外的many:man表,这使得优化很困难。
  • 当然,由于冗余标签的存在,我的方法可能比TOXI稍大一些,但这只占整个数据库的一小部分,并且性能提高可能会很明显。
  • li>
  • 它具有高度的可扩展性。
  • 它没有(因为不需要)替代AUTO_INCREMENT PK。因此,它比Scuttle好。
  • MySQLicious很烂,因为它无法使用索引({<1>前导通配符使用LIKE;对子字符串的错误命中)
  • 对于MySQL,请确保使用ENGINE = InnoDB,以获得“聚类”效果。

相关讨论(对于MySQL):
many:many mapping table optimization
ordered lists
并且,特别是对于WP用户, postmeta improvements