MySQL“ in子句”中的项目数


69

我有三个表来定义用户:

USER: user_id (int), username (varchar)
USER_METADATA_FIELD: user_metadata_field_id (int), field_name (varchar)
USER_METADATA: user_metadata_field_id (int), user_id (int), field_value (varchar)

我想创建一个对应用程序中的其他用户具有一定访问权限的中间层用户。为了确定已登录的用户可以访问哪些用户,我使用了如下子查询:

SELECT user_id FROM user WHERE user_id 
     IN (SELECT user_id 
         FROM user_metadata 
         WHERE user_metadata_field_id = 1 AND field_value = 'foo')

当前,我将子查询字符串存储在变量中,然后每次需要拉出用户列表时,将其动态插入到外部查询中。完成此操作后,我认为“最好只存储实际user_ids的字符串”。

因此,与其将其存储在变量中...

$subSql = "SELECT user_id FROM user_metadata WHERE user_metadata_field_id = 1 AND field_value = 'foo'";

...我实际上是执行查询并以这种方式存储结果...

$subSql = "12, 56, 89, 100, 1234, 890";

然后,当我需要拉一小部分登录用户有权访问的用户时,可以使用以下方法:

$sql = "SELECT user_id FROM user WHERE user_id IN ($subSql)";

最后是问题:

MySQL INCLAUSE中可以使用多少个项目?每次执行该外部查询时,必须存储实际的id而不是sub-sql语句,对吗?

Answers:


35

从一定数量开始,IN表速度更快。

MySQL 在其代码内部包含一些内容,这使得在大量常量值上构建范围比在嵌套循环中进行计算要慢。

有关性能的详细信息,请参见我的博客中的这篇文章:


嘿Quassnoi:对于您的性能测试以及您认为临时表更好的说法,似乎存在很多分歧。我认为您可能在这里错了。
IcedD​​ante

3
@IcedD​​ante:有些脚本可以重现我在博客文章中写的所有内容。您可以自由使用自己的脚本编写自己的博客文章,并演示我的错。否则,像这样的谈话只是热闹的。
Quassnoi

4
我知道这个问题很旧,但是您的回答没有回答真正的问题:“ MySQL IN CLAUSE中可以使用多少个项目?”
古斯曼


11

正如Quassnoi的回应所暗示的达到给定MySql版本的实现(*)施加的任何可能的限制之前,人们偶然发现了其他实际考虑因素。因此,随着管理员用户(或可能需要IN构造的其他条件)数量的增加,人们应寻求使用文字“ IN”的替代方式,例如使用临时(甚至永久性)表。

由于出于性能考虑,您正在考虑对“管理员用户”条件进行特殊处理,因此,我想提出评论和建议。

评论:这可能是过早优化的情况吗?
我不知道该数据库的详细信息,其数量,复杂性等。是的,我知道要对EAV(实体-属性-值)格式进行一些性能上的贡献,但我认为即使对于成功的企业,帐户数据库也很少会超过10,000个用户。因此,即使每个用户有很多属性,我们仍在查看相对较小的EAV表,这可能不需要这种优化。(另一方面,在其他领域可能会欢迎其他一些优化技巧)。
此外,相对于其他查询,典型的用例涉及到相对较少的帐户数据库查询,因此这是为应用程序的帐户相关功能提供任何微不足道的性能考虑的另一个原因。

建议: 可能使用“重新规范化的属性”
对于单值属性,尤其是如果属性较短,则可以在Entity表(在这种情况下为“ USER”表)中移动(或复制)它们。这会在插入或更新项目时引入一些逻辑,但这与许多联接(或子查询)相同,并且还提供了考虑多字段索引以支持最常见用例的机会。

(*)有lim脚吗?
我还没有听说过这样的限制。我知道Oracle有时有1,000个限制,而MSSQL没有。当然,所有服务器都基于SQL语句的总长度有限制,但这是一个很大的数目!如果一个人偶然发现了那个,他/她还有其他问题... ;-)


7

MySQL的IN子句本身没有这样的限制。我尝试了8000个元素,对我来说效果很好。堆栈溢出错误可能是声明的变量,


0

如果IN()子句中的值超过1000,MariaDB似乎会自动创建临时表以提高性能。您可以使用查看EXPLAIN

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.