MySQL"in clause"中的项目数

Bar*_*art 64 mysql sql in-clause

我有三个表来定义用户:

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)
Run Code Online (Sandbox Code Playgroud)

我想创建一个中间层用户,该用户可以访问应用程序中的其他用户.要确定登录使用的用户可以访问哪些用户,我使用如下的子查询:

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')
Run Code Online (Sandbox Code Playgroud)

目前,我将子查询字符串存储在变量中,然后在每次需要提取用户列表时将其动态插入到外部查询中.在这样做之后,我想,"只需存储一串实际的user_ids 就更好了".

所以不要将其存储在变量中......

$subSql = "SELECT user_id FROM user_metadata WHERE user_metadata_field_id = 1 AND field_value = 'foo'";
Run Code Online (Sandbox Code Playgroud)

...我实际执行查询并存储结果,如...

$subSql = "12, 56, 89, 100, 1234, 890";
Run Code Online (Sandbox Code Playgroud)

然后当我需要拉出登录用户可以访问的点亮用户时,我可以这样做:

$sql = "SELECT user_id FROM user WHERE user_id IN ($subSql)";
Run Code Online (Sandbox Code Playgroud)

最后问题是:

您可以在MySQL INCLAUSE中使用多少项?存储实际的id而不是sub-sql语句每次执行外部查询必须更快,对吧?

Red*_*ter 154

手册:

IN列表中的值数量仅受max_allowed_packet值限制.

  • 默认设置的示例是`max_allowed_pa​​cket | 1048576`(1 MB) (15认同)
  • +1回答问题.谢谢. (11认同)
  • [max_allowed_pa​​cket的默认值为4MB](http://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_max_allowed_pa​​cket) (3认同)

Qua*_*noi 34

从一定数量开始,IN表格更快.

MySQL 在其代码中有一些东西使得在大量常量值上构建范围比在嵌套循环中执行相同操作更慢.

有关性能详情,请参阅我的博客中的这篇文章

  • @IcedD​​ante:有一些脚本可以重现我在博文中写的所有内容.您可以使用自己的脚本自由编写自己的博客文章,并演示我的错误.否则,像这样的谈话只是热空气. (3认同)
  • 我知道这个问题已经过时了,但你的回答并没有回答真正的问题:"你可以在MySQL IN CLAUSE中使用多少项?" (3认同)

mjv*_*mjv 11

正如Quassnoi的回应中暗示的那样,达到给定MySql版本的实现(*)所施加的任何可能限制之前,人们会遇到其他实际考虑因素.因此,随着管理员用户的数量(或可能需要IN构造的其他标准)的增长,人们应该寻求使用文字"IN"的替代方法,例如使用临时(甚至永久)表.

由于您正在考虑特殊处理"管理员用户"标准,出于性能目的,我想提供评论和建议.

评论:这可能是过早优化的情况吗?
我不知道这个数据库的具体细节,它的数量,复杂性等等.是的,我知道要对EAV(实体 - 属性 - 值)格式付出一些性能,但我想即使对于成功的企业,账户数据库也很少超过10,000个用户.因此,即使每个用户拥有非常多的属性,我们仍然会查看相对较小的EAV表,这可能不需要这种类型的优化.(另一方面,其他一些优化技巧可能会受到欢迎).
此外,典型的用例涉及相对于其他查询相对较少的对帐户数据库的查询,因此这是对应用程序的帐户相关功能的任何非平凡性能考虑的另一个原因.

建议: 可能使用"重新规范化的属性"
对于单值的属性,特别是如果它们很短,可以在实体表中移动(或复制)它们(在本例中为"USER"表).这在插入或更新项目时引入了一些逻辑,但这与许多连接(或子查询)相同,并且还提供了考虑多字段索引以支持最常见用例的机会.

(*)有限制吗?
我还没有读到任何这样的限制; 我知道Oracle有一段时间有1000个限制,MSSQL没有; 当然所有服务器都有一个基于SQL语句总长度的限制,但这是一个非常大的数字!如果有人偶然发现那个,他/她还有其他问题... ;-)


小智 7

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