Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL海量内部连接查询导致响应缓慢_Mysql_Sql_Inner Join_Query Performance_Entity Attribute Value - Fatal编程技术网

MySQL海量内部连接查询导致响应缓慢

MySQL海量内部连接查询导致响应缓慢,mysql,sql,inner-join,query-performance,entity-attribute-value,Mysql,Sql,Inner Join,Query Performance,Entity Attribute Value,我读过其他相关的问题,但我的问题是独特的,因为它的结构 我的应用程序存储了大约10000多名用户的个人资料,这些资料由性别、体重、身高、头发颜色、眼睛颜色、舞蹈技能等参数定义。。。以此类推,比如说,大约100个属性 应用程序使用这些属性构造一个过滤器表单。用户正在使用此表单筛选数据库,因此构造了一个包含多个子查询的查询,每个子查询对应一个所使用的筛选器 问题是,如果使用8-9个以上的过滤器,引擎会在很长的时间内崩溃,我不得不在等待30米后终止进程 这就是数据库的结构 表def_属性这里是属性定义

我读过其他相关的问题,但我的问题是独特的,因为它的结构

我的应用程序存储了大约10000多名用户的个人资料,这些资料由性别、体重、身高、头发颜色、眼睛颜色、舞蹈技能等参数定义。。。以此类推,比如说,大约100个属性

应用程序使用这些属性构造一个过滤器表单。用户正在使用此表单筛选数据库,因此构造了一个包含多个子查询的查询,每个子查询对应一个所使用的筛选器

问题是,如果使用8-9个以上的过滤器,引擎会在很长的时间内崩溃,我不得不在等待30米后终止进程

这就是数据库的结构

表def_属性这里是属性定义

id-->用作值表中的属性id 表utilizatori用户定义,现在只使用列activ

id-->在其余表中命名为user_id 如果用户处于活动状态,则activ-->为1,并将显示列索引 表val_ATIBUTE存储每个用户的属性值

attr\u id-->索引的筛选器列的attrID 属性的属性值-->属性值 用户id列索引 例如,下面是一个由筛选表单构造的查询,它被忽略了:

SELECT DISTINCT Q1.user_id
FROM   (SELECT DISTINCT val_atribute.user_id
        FROM   val_atribute
        WHERE  attr_id = 45
               AND attr_value IN ( 'Actor', 'Actor Amator' )) Q1
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 46
                          AND Floor(Datediff(Curdate(), attr_value) / 365) >= '20') Q2
               ON Q1.user_id = Q2.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 46
                          AND Floor(Datediff(Curdate(), attr_value) / 365) <= '50') Q3
               ON Q2.user_id = Q3.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 47
                          AND attr_value IN ( 'feminin', 'masculin' )) Q4
               ON Q3.user_id = Q4.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 102
                          AND attr_value IN ( 'African', 'Asiatic', 'Caucazian', 'Metis' )) Q5
               ON Q4.user_id = Q5.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 103
                          AND attr_value >= 1) Q6
               ON Q5.user_id = Q6.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 103
                          AND attr_value <= 200) Q7
               ON Q6.user_id = Q7.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 104
                          AND attr_value >= 10) Q8
               ON Q7.user_id = Q8.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 104
                          AND attr_value <= 150) Q9
               ON Q8.user_id = Q9.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 107
                          AND attr_value IN ( 'Albastri', 'Caprui', 'Heterocrom', 'Verzi' )) Q10
               ON Q9.user_id = Q10.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 108
                          AND attr_value IN ( 'Blond', 'Brunet', 'Castaniu', 'Roscat', 'Saten' )) Q11
               ON Q10.user_id = Q11.user_id
       INNER JOIN (SELECT DISTINCT val_atribute.user_id
                   FROM   val_atribute
                   WHERE  attr_id = 109
                          AND attr_value IN ( 'Calvitie', 'Lung', 'Mediu', 'Scurt', 'Zero' )) Q12
               ON Q11.user_id = Q12.user_id
       INNER JOIN (SELECT DISTINCT utilizatori.id
                   FROM   utilizatori
                   WHERE  activ = 1) Q13
               ON Q12.user_id = Q13.id
GROUP  BY user_id
Q2正在计算年龄,因为我们只有属性[出生日期],并且筛选器Q2希望年龄>20

这里的最后一个查询Q13总是匹配表utilizatori中的活动用户

我认为笛卡尔级数有问题,但是 问题:如何重新生成查询以使其更快? 多谢各位

编辑/解决问题:

在Gordon Linoff的大力帮助下,我使用相同的过滤器构建了正确的查询:

选择u.id 来自utilizatori u 在存在的位置选择1 来自弗吉尼亚州瓦卢阿特里布特 其中va.user_id=u.id 和va.attr_id=45 和“Actor”、“Actor Amator”中的attr_值 并选择1 来自弗吉尼亚州瓦卢阿特里布特 其中va.user_id=u.id 和va.attr_id=46 和FloorDatediffCurdate,属性值/365>=20 并选择1 来自弗吉尼亚州瓦卢阿特里布特 其中va.user_id=u.id 和va.attr_id=46 和FloorDatediffCurdate,属性值/365=1 并选择1 来自弗吉尼亚州瓦卢阿特里布特 其中va.user_id=u.id 和va.attr_id=103 属性值=10 并选择1 来自弗吉尼亚州瓦卢阿特里布特 其中va.user_id=u.id 和va.attr_id=104
MySQL中的attr_value子查询是有问题的,select distinct会让事情变得更糟。您正在使用和连接子查询。我建议使用exists构建相同的逻辑

因此:


此版本的查询可以利用val_attributeuser_id、attr_id、attr_value上的索引。MySQL中的子查询是有问题的,select distinct会让事情变得更糟。您正在使用和连接子查询。我建议使用exists构建相同的逻辑

因此:


此版本的查询可以利用val_attributeuser_id、attr_id、attr_value上的索引。它应该更快,并且具有更好的可扩展性。

这是一个在臭名昭著的低效EAV模式设计上的变体

到目前为止,这个问题的最佳解决方案是对utilizatori进行全表扫描,并对属性表val_atribute进行多次探测以进行过滤

为了提高效率,val_atribute需要主键用户id,attr_id。不,这两列上单独的索引没有那么好

为了提高效率,您需要提取少量常用属性并添加索引。这样可以避免对10K个用户进行全表扫描,再加上大量的属性查找,从而将其减少到原来的一小部分


更多讨论:

这是臭名昭著的低效EAV模式设计的变体

到目前为止,这个问题的最佳解决方案是对utilizatori进行全表扫描,并对属性表val_atribute进行多次探测以进行过滤

为了提高效率,val_atribute需要主键用户id,attr_id。不,这两列上单独的索引没有那么好

为了提高效率,您需要提取少量常用属性并添加索引。这样可以避免对10K个用户进行全表扫描,再加上大量的属性查找,从而将其减少到原来的一小部分


更多讨论:

您选择了什么,为什么选择分组依据?我在上次查询中选择了活动用户用户id,
匹配12个过滤器,存储在val_atributeIf@GordonLinoff表中,每个用户的答案解决了您的问题,然后请将其标记为已接受。如果你的答案有所改进,那么请添加你的答案,而不是将其添加到问题中。您也可以,但必须等待48小时才能执行此操作。再次检查-1.5ms闻起来好像您运行了两次查询,并且查询缓存已打开。在选择后立即添加SQL\u NO\u缓存。@Rick James你是对的,使用SQL\u NO\u缓存查询花费了0.0055秒,是3倍多,但在我看来仍然非常好。你选择了什么,为什么是分组依据?我在上一次查询中选择了活动用户用户id,匹配12个筛选器,存储在表val_atributeIf@GordonLinoff中的每个用户的答案解决了您的问题,然后请将其标记为已接受。如果你的答案有所改进,那么请添加你的答案,而不是将其添加到问题中。您也可以,但必须等待48小时才能执行此操作。再次检查-1.5ms闻起来好像您运行了两次查询,并且查询缓存已打开。在选择后立即添加SQL\u NO\u缓存。@Rick James你是对的,使用SQL\u NO\u缓存查询花费了0.0055秒,这是3倍多,但在我看来仍然非常好,太多了!你的解决方案非常有效!使用完全相同的过滤器,现在查询需要0.0015秒。从30秒到0.0015秒。这是99.995%的提速。非常感谢!你的解决方案非常有效!使用完全相同的过滤器,现在查询需要0.0015秒。从30秒到0.0015秒。这是99.995%的速度。这确实是一个很好的方法,我看到了该方法的论点和潜力,但因为我没有看到任何DB结构的例子,只是一个理论方法,我想问你:我们创建的大表,将存储所有数据用户/过滤器/值?;将为每个筛选器/用户\u id/等设置一列,并为每个用户设置一行?谢谢。几个索引列,然后是所有100个属性的大JSON结构。列和索引将是第一个筛选。然后,应用程序在解压缩JSON后进行第二次过滤。所有属性都将在表中—10万行,大约有12列,可能每行2 KB。这加起来就是一个20MB的小表。这确实是一个很好的方法,我看到了该方法的论点和潜力,但因为我没有看到任何DB结构的示例,只是一个理论方法,我想问你:我们创建的大表将存储所有数据用户/过滤器/值?;将为每个筛选器/用户\u id/等设置一列,并为每个用户设置一行?谢谢。几个索引列,然后是所有100个属性的大JSON结构。列和索引将是第一个筛选。然后,应用程序在解压缩JSON后进行第二次过滤。所有属性都将在表中—10万行,大约有12列,可能每行2 KB。这相当于一个20MB的小表。
select u.*
from users u
where exists (select 1
              from val_atribute va
              where va.user_id = u.user_id and
                    va.attr_id = 45 and
                    va.attr_value in ( 'Actor', 'Actor Amator' )
             ) and
      exists (select 1
              from val_atribute va
              where va.user_id = u.user_id and
                    va.attr_id = 46 and
                    Floor(Datediff(Curdate(), va.attr_value) / 365) >= 20) Q2
             ) and
      . . .