MySQL中“in子句”中的条目数

我有三个表来定义用户:

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) 

我想要创build一个中间层用户,可以在应用程序中对其他用户有一定的访问权限。 要确定哪些用户login使用可以访问,我正在使用像下面这样的子查询:

 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') 

目前,我将子查询string存储在一个variables中,然后在每次需要拉取用户列表时,将其dynamic插入到外部查询中。 这样做后,我想,“它只是存储一个实际的user_idstring”。

所以,而不是将其存储在一个variables中…

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

我实际上执行查询和存储结果像这样…

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

然后,当我需要拉login用户有权访问的用户点燃,我可以这样做:

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

最后是问题:

MySQL IN CLAUSE中可以使用多less项? 每次执行外部查询时,存储实际的id而不是子sql语句的速度要快一些,对吧?

从某个数字开始, IN表格更快。

MySQL在代码中有一些东西,比在嵌套循环中做同样的事情更慢地构build大量的常量值。

在我的博客中看到这篇文章的性能细节:

  • 在MySQL中传递参数:IN列表与临时表

从手册 :

IN列表中的值的数量仅受限于max_allowed_packet值。

正如Quassnoi的回应所暗示的那样遇到由给定的MySql版本实现(*)施加的任何可能的限制之前 ,人们会考虑其他实际的考虑 。 因此,随着pipe理员用户(或可能需要IN构件的其他标准)的数量增加,人们应该设法使用字面“IN”的替代scheme,例如使用临时(甚至永久)表格。

由于您正在考虑对“pipe理员用户”标准进行特殊处理,所以为了提高性能,我想提供意见和build议。

评论:这可能是一个过早优化的情况吗?
我不知道这个数据库的具体细节,数量,复杂程度等。是的,我知道一些performance值得付给EAV(实体 – 属性 – 值)格式,但我在想即使是成功的企业,账户数据库也不会超过10,000个用户。 所以,即使每个用户有很多属性,我们仍然在寻找一个相对较小的EAV表,这可能不需要这种types的优化。 (另一方面,其他一些优化技巧可能会在其他领域受到欢迎)。
此外,与其他查询相比,典型的用例涉及对账户数据库的相对较less的查询,因此这是为了降低应用程序的与账户相关的特性的任何不重要的性能考虑的另一个原因。

build议:也许使用“重新规范化属性”
对于单值的属性,特别是短的属性,可以将它们移动(或复制)到实体表(本例中为“用户”表)。 这在插入或更新项目时引入了一些逻辑,但是这与许多联接(或子查询)相同,也提供了考虑多字段索引以支持最常见用例的机会。

(*)有没有限制?
我没有读到任何这样的限制; 我知道甲骨文在某个时候有1000个限制,MSSQL没有; 当然所有的服务器都有一个基于SQL语句总长度的限制,但这是一个非常大的数字! 如果有人偶然发现,他/她有其他问题… 😉

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

Interesting Posts