SQL语句创建许多连接并挂起数据库

时间:2017-10-05 14:44:09

标签: mysql sql database

SELECT Distinct org.id_name,org.id_region,org.id_inn,org.id_kpp,org.id_username, agreements.id_agr_code,
agreements.id_crat, agreements.id_project_name, agreements.comment, agreements.comment2, agreements.id_factor, agreements.id_name,
month1.id_date_money,month1.id_done,month2.id_date_money,month2.id_done,month3.id_date_money,month3.id_done,month4.id_date_money,
month4.id_done,month5.id_date_money,month5.id_done,month6.id_date_money,month6.id_done FROM agreements
inner join org on (org.id_org=agreements.id_org)
LEFT OUTER JOIN money as month1 ON (agreements.id_agr = month1.id_dogovor) and ( month1.id_date_money is NULL OR month1.id_date_money=:Month1)
LEFT OUTER JOIN money as month2 ON (agreements.id_agr = month2.id_dogovor) and ( month2.id_date_money is NULL OR month2.id_date_money=:Month2)
LEFT OUTER JOIN money as month3 ON (agreements.id_agr = month3.id_dogovor) and ( month3.id_date_money is NULL OR month3.id_date_money=:Month3)
LEFT OUTER JOIN money as month4 ON (agreements.id_agr = month4.id_dogovor) and ( month4.id_date_money is NULL OR month4.id_date_money=:Month4)
LEFT OUTER JOIN money as month5 ON (agreements.id_agr = month5.id_dogovor) and ( month5.id_date_money is NULL OR month5.id_date_money=:Month5)
LEFT OUTER JOIN money as month6 ON (agreements.id_agr = month6.id_dogovor) and ( month6.id_date_money is NULL OR month6.id_date_money=:Month6)
where agreements.id_old=:Archive
and case when :region is null then org.id_region=org.id_region else FIND_IN_SET(org.id_region, :region) end
and case when :users is null then org.id_user=org.id_user else FIND_IN_SET(org.id_user, :users) end
and case when :agrtype is null then agreements.id_type=agreements.id_type else FIND_IN_SET(agreements.id_type, :agrtype) end
and case when :agrproject is null then agreements.id_project_name=agreements.id_project_name else FIND_IN_SET(agreements.id_project_name, :agrproject) end
ORDER BY org.id_name 

MySQL中的这个SQL语句需要很长时间才能完成,并且在某些时候会挂起BD,因为它会创建很多根连接并说“复制到tmp_table"”。错误消息显示"与BD"。

的连接太多

我认为这是因为FIND_IN_SET,但我不确定。我无法找到一种不同的方法来重写这个SQL,以便它执行得更快,并且不会创建所有这些连接(它会一直创建它们,直到它填满最大值)。

这个想法是显示哪个组织在规定的月份内有哪些协议付款,哪些协议没有。区域过滤器的编号为01,05,09,23,26,91和e.t.c,用户过滤器的编号为user_id整数。 agrtypes的过滤器在字符串中,agrprojects也在字符串中。 ID_old是一个布尔标志。 ID_agr,ID_Dogovor和id_org是主键Integer。

1 个答案:

答案 0 :(得分:1)

agreements.id_old是一个ID还是只是一些标志,表明该ID是旧格式还是其他?如果它真的是一个ID,它可能不会经常在表中出现。也许只是一次?然后列上的索引应该使访问速度非常快。您还应该在money.id_dogovor上有一个索引。

我建议使用以下索引:

create index idx1 on agreements(id_old, id_org, id_agr);
create index idx2 on money(id_dogovor, id_date_money, id_done);

(我猜测org(id_org)上存在唯一索引,因为它似乎是表的主键。)