我已经尝试了一切我能想到的速度来加速这个查询,但它仍然需要大约2.5秒。
该表格为images_tags(约4百万行): 这是表EXPLAIN:
Field Type Null Key Default
image_ids int(7) unsigned NO PRI NULL
tags_id int(7) unsigned NO PRI NULL
以下是索引:
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type
images_tags 0 PRIMARY 1 image_ids A NULL NULL NULL BTREE
images_tags 0 PRIMARY 2 tags_id A 4408605 NULL NULL BTREE
images_tags 1 image_ids 1 image_ids A 734767 NULL NULL BTREE
以下是查询:
select image_ids
from images_tags
where tags_id in (1, 2, 21, 846, 3175, 4290, 6591, 9357, 9594, 14289, 43364, 135019, 151295, 208803, 704452)
group by image_ids
order by count(*) desc
limit 10
这是查询EXPLAIN:
select_type table type possible_keys key key_len ref rows Extra
SIMPLE vids_x_tags index join_tags_id join_vids_id_unique 8 NULL 4408605 Using where; Using index; Using temporary; Using filesort
目标是获得与这些标签最匹配的10张图片。 我试过搞乱这些变量几乎没有改进:
有没有办法加快这个查询的速度?大约有700K图像并且它总是在增长,所以我不想将结果缓存超过一天或两天,并且必须为每个图像完成,所以重新缓存许多图像查询是不可能的。
答案 0 :(得分:1)
在这种链接(结点,多对多)表中,在(a, b)
和(b, a)
上都有两个复合索引几乎总是有用的。你只有一个(主要索引)而不是另一个。
如果表中没有其他列,则根本不需要任何其他索引。
因此,您应该添加(tags_id, image_ids)
索引并删除(image_ids)
多余的索引:
ALTER TABLE images_tags
DROP INDEX image_ids,
ADD INDEX tag_image_IDX -- choose a name for the index
(tags_id, image_ids) ;
关于特定查询的索引效率取决于很多因素,主要取决于图像和标签的分布(IN
列表中的15个标签有多受欢迎?)
答案 1 :(得分:1)
在查询的EXPLAIN
输出中,您会看到key
列与possible_keys
列表中的任何项都不匹配。这意味着虽然数据是从索引中获取的(在许多情况下,它比实际表小,因为它跨越较少的列),但引擎仍然必须遍历所有行。
如果您想要正确使用索引来加速此查询,则应添加一个标记为 first (可能只是)组件。
顺便说一下,image_ids
上的索引只有一点用处,因为主键也可以用来提供这些信息。通常,可以使用多行索引来加速查询,这些查询为所有这些列提供显式值(或范围),或者从第一列开始提供连续的列集。换句话说,两列索引也会像第一列的单列索引一样,但它的第二列本身就没有多大用处,这就是你所拥有的。
作为在tags_id
上添加密钥并在image_ids
上删除密钥的替代方法,您可以将密钥保持在image_ids
上,并反转列的顺序首要的关键。然后,主键也可用于回答仅标记查询。如果您通过标签而不是图像更频繁地查询表格,那么我建议采用这种方法。