Mysql 使用大型where子句优化SQL查询

Mysql 使用大型where子句优化SQL查询,mysql,sql,query-performance,Mysql,Sql,Query Performance,我正在开发一个系统(与Laravel合作),在这个系统中,用户可以填充一些过滤器来获取他们需要的数据。 数据不是实时准备的,一旦设置了过滤器,就会将作业推送到队列中,并且一旦查询完成,就会创建一个CSV文件。然后,用户会收到一封包含创建的文件的电子邮件,以便下载该文件 我在作业中看到一些错误,处理一个作业需要超过30分钟,当我检查时,我看到一些用户创建了超过600个值的过滤器 此过滤器值的转换方式如下: SELECT filed1, field2, field6

我正在开发一个系统(与Laravel合作),在这个系统中,用户可以填充一些过滤器来获取他们需要的数据。 数据不是实时准备的,一旦设置了过滤器,就会将作业推送到队列中,并且一旦查询完成,就会创建一个CSV文件。然后,用户会收到一封包含创建的文件的电子邮件,以便下载该文件

我在作业中看到一些错误,处理一个作业需要超过30分钟,当我检查时,我看到一些用户创建了超过600个值的过滤器

此过滤器值的转换方式如下:

SELECT filed1, 
       field2, 
       field6 
FROM   table 
       INNER JOIN table2 
               ON table.id = table2.cid 
/* this is how we try not to give same data to the users again so we used NOT IN */ 
WHERE  table.id NOT IN(SELECT data_id 
                       FROM   data_access 
                       WHERE  data_user = 26) 
       AND ( /* this bit is auto populated with the filter values */ 
           table2.filed_a = 'text a' 
            OR table2.filed_a = 'text b' 
            OR table2.filed_a = 'text c' ) 
SELECT ?.filed1, ?.field2, ?.field6  -- qualify column names (but no effect on performance)
FROM table t JOIN
     table2 t2
     ON t.id = t2.cid 

WHERE NOT EXISTS (SELECT 1
                  FROM data_access da
                  WHERE t.id = da.data_id AND da.data_user = 26
                 ) AND
     t2.filed_a IN ('text a', 'text b', 'text c') ;
我没想到用户会对一个巨大的过滤器进行疯狂的微调。他们可以这样做,但需要一个解决方案来加快查询速度

一种方法是使用筛选器值动态创建临时表,并转换
内部联接的查询,但不确定这是否会提高性能。
此外,在正常的一天中,系统需要创建至少40个ish临时表,然后删除它们。从长远来看,这会成为另一个问题吗


除了临时表方法之外,我希望听到任何其他可能帮助我解决此问题的建议。

我建议这样编写查询:

SELECT filed1, 
       field2, 
       field6 
FROM   table 
       INNER JOIN table2 
               ON table.id = table2.cid 
/* this is how we try not to give same data to the users again so we used NOT IN */ 
WHERE  table.id NOT IN(SELECT data_id 
                       FROM   data_access 
                       WHERE  data_user = 26) 
       AND ( /* this bit is auto populated with the filter values */ 
           table2.filed_a = 'text a' 
            OR table2.filed_a = 'text b' 
            OR table2.filed_a = 'text c' ) 
SELECT ?.filed1, ?.field2, ?.field6  -- qualify column names (but no effect on performance)
FROM table t JOIN
     table2 t2
     ON t.id = t2.cid 

WHERE NOT EXISTS (SELECT 1
                  FROM data_access da
                  WHERE t.id = da.data_id AND da.data_user = 26
                 ) AND
     t2.filed_a IN ('text a', 'text b', 'text c') ;
然后我会推荐索引。很可能:

  • 表2(已存档,cid)
  • table1(id)
    (如果
    id
    已经是主键,则可能不需要)
  • 数据访问(数据id、数据用户)

您可以将其作为自己的查询进行测试。我不知道如何让Laravel制作这个(假设它满足您的性能目标)。

您是否检查了
解释计划?我这样问是因为
中的子查询与外部查询不相关,这意味着MySQL可能只运行一次,并缓存结果。因此,我不确定这是否是您在这里遇到的最大瓶颈。事实上,
not in
表达式中的子查询不相关对我来说似乎非常可疑,特别是考虑到相关的注释。您已经尝试更改table.id not in的位置(子查询)使用左连接data\u access ON data\u access.data\u id=table.id,其中data\u access.data\u id为空?