2

我已经尝试了我能想到的一切来加快这个查询,但它仍然需要大约 2.5 秒。

该表是 images_tags(约 400 万行):这是表说明:

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

这是查询解释:

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 张图像。我尝试过处理这些变量,但几乎没有改善:

  • max_heap_table_size
  • tmp_table_size
  • myisam_sort_buffer_size
  • 读取缓冲区大小
  • 排序缓冲区大小
  • read_rnd_buffer_size
  • net_buffer_length
  • preload_buffer_size
  • key_buffer_size

有什么方法可以大大加快这个查询的速度吗?大约有 700K 图像并且它一直在增长,所以我不想将结果缓存超过一两天,并且必须为每个图像完成,因此重新缓存许多查询是不可能的。

4

2 回答 2

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 个标签有多受欢迎?)

于 2012-09-26T07:00:19.863 回答
1

EXPLAIN查询的输出中,您会看到该key列与列表中的任何项目都不匹配possible_keys。这意味着尽管数据是从索引中获取的(在许多情况下,它比实际表小,因为它跨越的列更少),引擎仍然必须遍历所有行。

如果您想正确使用索引来加速此查询,您应该添加一个带有标记的索引作为它的第一个(可能是唯一的)组件。

顺便说一句,image_ids仅上的索引几乎没有用,因为主键也可以用来提供该信息。通常,多行索引可用于加速查询,这些查询为所有这些列或从第一列开始的连续列集提供显式值(或范围)。换句话说,双列索引也将像单列索引一样用于它的第一列,但它的第二列本身并没有多大用处,这就是你在这里所拥有的。

作为添加键tags_id和删除键的替代方法image_ids,您可以保持键保持image_ids原样,并反转主键的列顺序。然后主键也可以用于回答仅标记查询。如果您通过标签而不是图像更频繁地查询表格,那么我建议使用这种方法。

于 2012-09-26T07:00:47.240 回答