2017-10-05 8 views
0
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 

このSQL文は完了するまでに非常に多くの時間を要し、いくつかの時点では、ルートとなる多くの接続を作成し、 "コピーするtmp_table "エラーメッセージに「BDへの接続が多すぎます」と表示されます。SQLステートメントは多くの接続を作成し、データベースをハングします

これは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

あなたは、データベースを正規化していないとしてコラムで区切られたリストを代わりに列に入れることに決めたので、速度に対しても決定しました。どのレコードに特定の領域が含まれているかを知るためには、すべてのレコードを読み取ってチェックする必要がありますが、org_regionテーブルではDBMSはおそらくインデックスを使用します。 –

答えて

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)に一意索引が存在すると推測。)

+0

id_oldはブール値のフラグです。 – SovereignSun

+0

なぜクエリは "tmp_tableへのコピー"と呼ばれる多くの接続を作成しますか?このため、クエリが失敗し、自動的に終了するまで誰もdbに接続できません。 – SovereignSun

+0

ありがとう、これは、最終的には、働いた。 – SovereignSun

関連する問題