0

私は、永続化のために ADO.Net 2.0 を使用して ASP.net Web フォームで作成された古い時間記録システムを担当しています。

基本的に、このシステムでは、ユーザーが現在行っている作業の詳細、作業を完了するために割り当てられた時間、および現在までの作業に費やした時間の詳細を追加できます。

システムには、SQL クエリに基づくレポートを含むレポート機能もあります。最近、システムから実行される多くのレポートの実行が非常に遅くなっていることに気付きました。データベースには約 11 個のテーブルがあり、あまり多くのデータを保存していません。27,000 レコードは、1 つのテーブルが保持するレコードの最大数であり、テーブルの大部分は 1,500 レコードをはるかに下回っています。

したがって、この問題は大量のデータに関連しているとは思いません.SQLクエリの構成が不十分であり、データベース設計にも同じことが当てはまる可能性が高いと思います.

たとえば、これに似たクエリがあります

@start_date datetime, 
@end_date datetime,
@org_id int 

select distinct t1.timesheet_id, 
                t1.proposal_job_ref, 
                t1.work_date AS [Work Date], 
                consultant.consultant_fname + ' ' + consultant.consultant_lname AS [Person], 
                proposal.proposal_title AS [Work Title], 
                t1.timesheet_time AS [Hours],

--GET TOTAL DAYS ASSIGNED TO PROPOSAL
(select sum(proposal_time_assigned.days_assigned)-- * 8.0) 
from proposal_time_assigned
where proposal_time_assigned.proposal_ref_code = t1.proposal_job_ref ) 
as [Total Days Assigned],


--GET TOTAL DAYS SPENT ON THE PROPOSAL SINCE 1ST APRIL 2013 
(select isnull(sum(t2.timesheet_time / 8.0), '0') 
from timesheet_entries t2 
where t2.proposal_job_ref = t1.proposal_job_ref 
and t2.work_date <= t1.work_date 
and t2.work_date >= '01/04/2013' ) 
as [Days Spent Since 1st April 2013],

--GET TOTAL DAYS REMAINING ON THE PROPOSAL 
(select sum(proposal_time_assigned.days_assigned) 
from proposal_time_assigned 
where proposal_time_assigned.proposal_ref_code = t1.proposal_job_ref )
- 
(select sum(t2.timesheet_time / 8.0) 
from timesheet_entries t2 
where t2.proposal_job_ref = t1.proposal_job_ref 
and t2.work_date <= t1.work_date
 ) as [Total Days Remaining]

from timesheet_entries t1, 
consultant, 
proposal, 
proposal_time_assigned 

where (proposal_time_assigned.consultant_id = consultant.consultant_id)
     and (t1.proposal_job_ref = proposal.proposal_ref_code) 
     and (proposal_time_assigned.proposal_ref_code = t1.proposal_job_ref)
     and (t1.code_id = @org_id) and (t1.work_date >= @start_date) and (t1.work_date <= @end_date) 
    and (t1.proposal_job_ref <> '0')

order by 2, 3

レポートのデータを返すことが期待されています。上記のクエリで何が起こっているかを誰かが追跡できるかどうかさえわかりませんが、基本的には、除算、乗算、減算など、かなりの数の計算が行われています。これがSQLクエリの速度を低下させていると推測しています。

私の質問は、上記のクエリを高速化する方法を提案するのに十分な意味を持っている人さえいるでしょうか。

また、上記のような計算は、SQL クエリで実行されたことがありますか? または、これはコード内で行う必要がありますか?

これで何か助けていただければ幸いです。

ありがとう。

4

3 に答える 3

1

与えられた情報に基づいて、特定のテーブルの関係について知識に基づいた推測を行う必要がありました。テーブル構造、インデックスなどを投稿すると、このクエリで残りの列を完成させることができます。

現在、このクエリは、KEY「timesheet_id and proposal_job_ref」の「割り当て日数」、「滞在日数」、および「残り日数」を計算します。

私たちが見なければならないのは、「work_date」、「timesheet_time」、「[Person]」、「proposal_title」がそれにどのように関連付けられているかです。これらは人物別の計算で、Proposal_title も同様ですか?

sqlfiddleを使用してサンプル データと出力を提供することで、推測を行う代わりに完全なデータの意味を理解することができます。

    SELECT 
             q1.timesheet_id
            ,q1.proposal_job_ref
            ,q1.[Total Days Assigned]
            ,q2.[Days Spent Since 1st April 2013]
            ,(
                q1.[Total Days Assigned] 
                - 
                q2.[Days Spent Since 1st April 2013]
            ) AS [Total Days Remaining]
    FROM
    (
        select 
            t1.timesheet_id
            ,t1.proposal_job_ref
            ,sum(t4.days_assigned) as [Total Days Assigned]
        from tbl1.timesheet_entries t1
        JOIN tbl1.proposal t2
            ON t1.proposal_job_ref=t2.proposal_ref_code
        JOIN tbl1.proposal_time_assigned t4
            ON t4.proposal_ref_code = t1.proposal_job_ref
        JOIN tbl1.consultant t3
            ON t3.consultant_id=t4.consultant_id
        WHERE t1.code_id = @org_id
            AND t1.work_date BETWEEN @start_date AND @end_date
            AND t1.proposal_job_ref <> '0'
        GROUP BY t1.timesheet_id,t1.proposal_job_ref
    )q1
    JOIN
    (
        select 
            tbl1.timesheet_id,tbl1.proposal_job_ref
            ,isnull(sum(tbl1.timesheet_time / 8.0), '0') AS [Days Spent Since 1st April 2013]
        from tbl1.timesheet_entries tbl1
        JOIN tbl1.timesheet_entries tbl2
            ON tbl1.proposal_job_ref=tbl2.proposal_job_ref
            AND tbl2.work_date <= tbl1.work_date
            AND tbl2.work_date >= '01/04/2013'
        WHERE tbl1.code_id = @org_id
            AND tbl1.work_date BETWEEN @start_date AND @end_date
            AND tbl1.proposal_job_ref <> '0'
        GROUP BY tbl1.timesheet_id,tbl1.proposal_job_ref
    )q2
        ON q1.timesheet_id=q2.timesheet_id 
        AND q1.proposal_job_ref=q2.proposal_job_ref
于 2013-11-11T17:01:41.633 に答える
1

あなたのクエリに表示される問題は次のとおりです。

1> テーブルにエイリアス名が提供されていません。2> WITH 句の代わりにサブクエリが使用されます (実行コストがかかります)。

私があなたのクエリを書くとしたら、それは次のようになります:

select distinct t1.timesheet_id, 
                t1.proposal_job_ref, 
                t1.work_date AS [Work Date], 
                c1.consultant_fname + ' ' + c1.consultant_lname AS [Person], 
                p1.proposal_title AS [Work Title], 
                t1.timesheet_time AS [Hours],

--GET TOTAL DAYS ASSIGNED TO PROPOSAL
(select sum(pta2.days_assigned)-- * 8.0) 
from proposal_time_assigned pta2
where pta2.proposal_ref_code = t1.proposal_job_ref ) 
as [Total Days Assigned],


--GET TOTAL DAYS SPENT ON THE PROPOSAL SINCE 1ST APRIL 2013 
(select isnull(sum(t2.timesheet_time / 8.0), 0) 
from timesheet_entries t2 
where t2.proposal_job_ref = t1.proposal_job_ref 
and t2.work_date <= t1.work_date 
and t2.work_date >= '01/04/2013' ) 
as [Days Spent Since 1st April 2013],

--GET TOTAL DAYS REMAINING ON THE PROPOSAL 
(select sum(pta2.days_assigned) 
from proposal_time_assigned pta2
where pta2.proposal_ref_code = t1.proposal_job_ref )
- 
(select sum(t2.timesheet_time / 8.0) 
from timesheet_entries t2 
where t2.proposal_job_ref = t1.proposal_job_ref 
and t2.work_date <= t1.work_date
 ) as [Total Days Remaining]

from timesheet_entries t1, 
consultant c1, 
proposal p1, 
proposal_time_assigned pta1

where (pta1.consultant_id = c1.consultant_id)
     and (t1.proposal_job_ref = p1.proposal_ref_code) 
     and (pta1.proposal_ref_code = t1.proposal_job_ref)
     and (t1.code_id = @org_id) and (t1.work_date >= @start_date) and (t1.work_date <= @end_date) 
    and (t1.proposal_job_ref <> '0')

order by 2, 3

インデックス作成オプションと各テーブルから処理されるレコード数については、上記のクエリを確認してください。

于 2013-11-08T18:22:00.077 に答える