优化SELECT ... WHERE IN(...)

时间:2011-09-26 06:22:08

标签: mysql performance memcached

我从外部系统收到一系列产品ID。我必须显示保留序列的产品信息。

我正在使用以下选项:

SELECT * FROM  products
WHERE  prodid in (10331,11639,12127..) ORDER BY Field(prodid, 10331,11639,12127...);

序列可以包含20个ID。 prodid有b-tree索引。

这是非常频繁的查询,我正试图找到提高系统该部分性能的方法。现在这个查询的平均时间是0.14-0.2秒 我想减少时间到0.01-0.05秒。

最好的方法是什么? MySQL HASH索引,在memcached中存储产品ID,还是其他东西?

3 个答案:

答案 0 :(得分:1)

SELECT * FROM  products                         <<-- select * is non-optimal
WHERE  prodid in (10331,11639,12127..) 
ORDER BY Field(prodid, 10331,11639,12127...);   <<-- your problem is here

首先在prodid上放一个索引,看@ Anthony的回答。

将查询更改为:

SELECT only,the,fields,you,need FROM  products
WHERE  prodid in (10331,11639,12127..) 
ORDER BY prodid

如果您确保IN列表在提交到IN子句之前按升序排序,则order by prodid将产生相同的结果als order by field(...

  • 使用函数而不是字段会导致使用索引的任何机会,导致速度变慢。
  • select *将获取您可能不需要的数据,从而导致额外的磁盘访问,额外的内存使用和额外的网络流量。
  • 在InnoDB上,如果你只有select索引字段,MySQL将永远不会读取表格,但只有索引节省时间(在你的情况下,这可能不是问题) < / LI>
  

最好的方法是什么? MySQL HASH索引,在memcached中存储产品ID,还是其他什么?

你可以使用一些技巧。

  • 如果products表不是太大,可以将其设为memory表,该表存储在RAM中。不要为大桌子这样做,它会减慢其他事情。
    您只能在内存表上使用hash索引。
  • 如果prodid是连续的,您可以使用BETWEEN 1000 AND 1019代替
    IN (1000, 1001 ..., 1019)

答案 1 :(得分:1)

您可以尝试创建结果联合:

SELECT * FROM  products WHERE prodid = 10331
UNION ALL
SELECT * FROM  products WHERE prodid = 11639
UNION ALL
.
.
UNION ALL
SELECT * FROM  products WHERE prodid = 12127

答案 2 :(得分:0)

您可以尝试使用以下查询在prodid列上添加索引:

CREATE INDEX index_name
ON products (prodid); 

有关详情,请参阅this post.