Mysql SQL WHERE IN(ID1、ID2、ID3)与WHERE UNIQUE_ID=IDX

Mysql SQL WHERE IN(ID1、ID2、ID3)与WHERE UNIQUE_ID=IDX,mysql,query-optimization,Mysql,Query Optimization,我用一些虚拟数据创建了一个表。表格(文章)由id、作者id、标题、描述组成,表格(作者)由作者id、姓名、文章列表组成 根据应用程序流程,首先我会拿出作者列表,这将给我作者姓名、文章列表和id。当用户在作者内部导航时,我可以通过两种方式获得所有文章的列表 首先 SELECT * FROM articles WHERE author_id = 100; 其次,如果我把所有文章的列表以列表的形式保存在我的作者表中,那么我可以使用 SELECT * FROM articles WHE

我用一些虚拟数据创建了一个表。表格(文章)由id、作者id、标题、描述组成,表格(作者)由作者id、姓名、文章列表组成

根据应用程序流程,首先我会拿出作者列表,这将给我作者姓名、文章列表和id。当用户在作者内部导航时,我可以通过两种方式获得所有文章的列表

首先

SELECT * FROM  articles WHERE  author_id = 100;
其次,如果我把所有文章的列表以列表的形式保存在我的作者表中,那么我可以使用

SELECT * 
  FROM  articles 
 WHERE id IN (100, 1100, 2100, 3100, 4100, 5100, 6100, 
            7100, 8100, 9100, 10100, 11100, 12100, 13100, 
            14100, 15100, 16100, 17100, 18100, 19100, 20100,
            21100, 22100, 23100, 24100, 25100, 26100, 27100,
            28100, 29100, 30100, 31100, 32100, 33100, 34100);
第一次查询耗时0.0329秒,第二次查询耗时0.0017秒

我无法理解为什么第一个查询比第二个查询花费更多的时间

据我所知,第二个查询的执行方式如下

SELECT * 
  FROM articles 
 WHERE id = 100 
    OR id = 1100 
    OR id = 2100... and so on

这可能是因为有数千个作者ID,并且:

 SELECT * FROM  articles WHERE  author_id = 100;
需要遍历每一行,因为它应用于整个列行

以及:

 SELECT * FROM  articles WHERE id IN (100, 1100, 2100, 3100, 4100, 5100, 6100, 7100, 8100, 9100, 10100, 11100, 12100, 13100, 14100, 15100, 16100, 17100, 18100, 19100, 20100, 21100, 22100, 23100, 24100, 25100, 26100, 27100, 28100, 29100, 30100, 31100, 32100, 33100, 34100);
它们是有限的记录,只需检查一次id,就可以通过使用内存加快遍历速度。

缓存

如果启动服务器,然后运行查询,则缓冲池(或表缓存或…)中没有任何内容。所以需要打开几个文件,读取几个块。32.9ms可能表示您需要以大约10ms的速度敲击磁盘(如果是HDD)3次

如果再次运行相同的查询,所有内容都将被缓存,并且只需几毫秒,通常不到10毫秒

因为第一个查询用一些东西初始化了缓存,所以第二个查询找到了它所需要的大部分(可能是全部)块。所以,它可能只是CPU,没有I/O。1.7ms是合理的

一个可能的问题。。。是否已打开“查询缓存”?如果是这样,则(在某些情况下)后续执行任何
SELECT
将在QC中找到结果集,并返回速度非常快,可能小于1ms。确保避免QC的一种方法(对于实际计时)是执行
选择SQL\u NO\u缓存…

您呈现的
查询已优化为您呈现的
中的
。也就是说,它们最终是相同的。(将
与不同的列一起使用是性能杀手;这里的情况并非如此。)

计时提示:

  • 使用
    选择SQL\u NO\u缓存…
    (以避免QC)
  • 运行查询两次并使用第二个计时。(这样可以避免其他缓存问题。)
现在来分析如果您在
作者id
上没有任何索引会发生什么

  • 这两个查询都将扫描整个表
  • 显然,这是一个相对较小的表,因为您可以在32.9毫秒内阅读所有内容
  • 32.9和1.7之间的差异只是缓存。(我有一个经验法则,这两者之间的比率是10。对于这个指标,32.9/1.7与我的RoT非常接近,足以支持它。)

如果您有
索引(author\u id)
,这两个查询可能运行得更快,无论是否缓存。

您是否有
author\u id
上的索引?您可以要求数据库
解释查询是如何运行的。这一切都取决于统计数据和其他因素DB查询性能取决于许多因素,最显著的是索引的存在和定义,以及与DB引擎可用内存相关的表大小。例如,如果ARTICLES表在
id
上有索引,但在
author\u id
上没有索引,那么第二个查询执行得更快是很正常的。如果整个表都在内存中,则第一个查询可能会产生读取成本,而第二个查询则会从内存中的数据中获益。请勿将项目ID存储在作者表的字段中。这个想法真的很糟糕,看@Shadow,你的说法是正确的,但与这篇文章无关。我不认为OP是在一列中存储逗号分隔的id列表。