MySQL中的项目数;在第条中;

MySQL中的项目数;在第条中;,sql,mysql,in-clause,Sql,Mysql,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) 我想创建一个中间层用户,该用户可以访问应用程序中的其他用户。为了确定登录用户可以访问哪

我有三个表来定义用户:

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')
目前,我将子查询字符串存储在一个变量中,然后在每次需要提取用户列表时动态地将其插入到外部查询中。这样做之后,我想,“最好只存储一个实际的
用户id
s字符串”

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

$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
in
子句中可以使用多少项?每次执行外部查询时,存储实际ID而不是子sql语句必须更快,对吗?

从某个数字开始,表中的
更快

MySQL
的代码中有一些东西使得在大量常量值上构建范围比在嵌套循环中构建范围要慢

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


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

由于您正在考虑对“管理员用户”标准的特殊处理,出于性能目的,我想提出一点意见和建议

评论:这可能是过早优化的情况吗?
我不知道该数据库的具体情况、容量、复杂性等。是的,我知道EAV(实体属性值)格式的一些性能优势,但我认为即使是成功的企业,accounts数据库的用户数也很少超过10000。因此,即使每个用户有很多属性,我们仍然在寻找一个相对较小的EAV表,这可能不需要这种类型的优化。(另一方面,一些其他优化技巧可能在其他领域受到欢迎)。
此外,与其他查询相比,典型用例涉及到对帐户数据库的相对较少的查询,因此,这是为应用程序的帐户相关功能取消任何非琐碎的性能考虑的另一个原因

建议:可能使用“重新规范化属性”
对于单值属性,尤其是短属性,可以在实体表中移动(或复制)(在本例中为“用户”表)。在时间项插入或更新时,引入了一点逻辑,但这也包含了许多连接(或子查询),也提供了考虑多字段索引以支持最常用的用例的机会。 (*)是否有限制?

我还没有读到任何这样的限制;我知道甲骨文有时有1000个限制,MSSQL没有;当然,所有服务器都有一个基于SQL语句总长度的限制,但这确实是一个很大的数字!如果一个人偶然发现了这个问题,他/她还有其他问题…;-)

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

来自:


列表中的
值的数量仅受该值的限制。

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

看到这一点。默认设置的一个示例是
max_allowed_packet | 1048576
(1 MB)Hey Quassnoi:对于性能测试和临时表更好的断言,似乎存在很多分歧。我想你可能错了。@IcedDante:有脚本可以复制我在博客文章中所写的一切。你可以自由地写你自己的博客文章,用你自己的脚本,并证明我是多么的错误。我知道这个问题很老了,但你的回答并没有回答真正的问题:“在MySQL in子句中可以使用多少项?”