views:

23

answers:

1

I was asked to do a report that combines 3 different crystal reports that we use. Already those reports are very slow and heavy and making 1 big one was out of the question. SO I created a little apps in VS 2010.

My main problem is this, I have 3 Datatable (same schema) that were created with the Dataset designer that I need to combine. I created an empty table to store the combined value. The queries are already pretty big so combining them in a SQL query is really out of the question.

Also I do not have write access to the SQL server (2005), because the server is maintained by the company that created our MRP program. Although I could always ask support to add a view to the server.

So my 3 datatable consist of Labor Cost, Material Cost and subcontracting Cost. I need to create a total cost table that adds all of the Cost column of each table by ID. All the table have keys to find and select them.

The problem is that when i fetch all of the current job it is ok (500ms for 400 records), because I have a query that will fetch only the working job. Problem is with Inventory, since I do not know since when those Job were finished I have to fetch the entire database (around 10000 jobs with subqueries that each have up to 100 records) and this for my 3 tables. This takes around 5000 to 8000ms, although it is very fast compared to the crystal report there is one problem.

I need to create a summary table that will combine all these different tables I created, But I also need to do them 2 times, 1 time for each date that is outputted. So my data always changes, because they are based on a Date parameter. Right now it will take around 12-20sec to fetch them all.

I need a way to reduce the load time, here is what I tried.

  • Tried a for loop to combine the 3 tables
  • Then tried with the DataReader class to read each line and used the FindBy*Key* methods that the dataset designer created to find the value in the other table, and I have to do this 2 time. (it seems to go a little bit faster than the for loop)
  • Tried with Linq, don't think it is possible, and will it give more performance?
  • Tried to do a dynamic query that use "WHERE IN Comma Separated List" (that actually doubled the time of execution, compared to fetching all of the database)
  • Tried to join my Inventory query to the my Cost queries (that also increased the time it took)

1 - So is there any way to combine my tables more effectively? What is the fastest way to Merge and Sum my records of my 3 tables?

2 - Is there any way to increase performance of my queries without having write access to the server?

Below is some of the code I used for reference :

    public static void Fill()
    {

        DateTime Date = Data.Date;

        AllieesDBTableAdapters.CoutMatTableAdapter mat = new AllieesDBTableAdapters.CoutMatTableAdapter();
        AllieesDBTableAdapters.CoutLaborTableAdapter lab = new AllieesDBTableAdapters.CoutLaborTableAdapter();
        AllieesDBTableAdapters.CoutSTTableAdapter st = new AllieesDBTableAdapters.CoutSTTableAdapter();

        Data.allieesDB.CoutTOT.Clear();

        //Around 2 sec each Fill
        mat.FillUni(Data.allieesDB.CoutMat, Date);
        Data.allieesDB.CoutMat.CopyToDataTable(Data.allieesDB.CoutTOT, LoadOption.OverwriteChanges);

        lab.FillUni(Data.allieesDB.CoutLabor, Date);
        MergeTable(Data.allieesDB.CoutLabor);

        st.FillUni(Data.allieesDB.CoutST, Date);
        MergeTable(Data.allieesDB.CoutST);

    }

Here is the MergeTable Methods (The For loop I tried is in Comment)

    private static void MergeTable(DataTable Table)
    {

        AllieesDB.CoutTOTDataTable dtTOT = Data.allieesDB.CoutTOT;

        DataTableReader r = new DataTableReader(Table);


        while (r.Read())
        {
            DataRow drToT = dtTOT.FindByWO(r.GetValue(2).ToString());

            if (drToT != null)
            {
                drToT["Cout"] = (decimal)drToT["Cout"] + (decimal)r.GetValue(3);
            } else
            {

                EA_CoutsDesVentes.AllieesDB.CoutTOTRow row = dtTOT.NewCoutTOTRow();

                for (int j = 0; j < r.FieldCount; j++)
                {
                    if (r.GetValue(j) != null)
                    {
                        row[j] = r.GetValue(j);
                    } else
                    {
                        row[j] = null;
                    }
                }

                dtTOT.AddCoutTOTRow(row);
            }
            Application.DoEvents();
        }

        //try
        //{
        //    for (int i = 0; i < Table.Rows.Count; i++)
        //    {
        //        DataRow drSource = Table.Rows[i];
        //        DataRow drToT = dtTOT.FindByWO(drSource["WO"].ToString());

        //if (drToT != null)
        //{
        //    drToT["Cout"] = (decimal)drToT["Cout"] + (decimal)drSource["Cout"];
        //} else
        //{
        //    
        //    EA_CoutsDesVentes.AllieesDB.CoutTOTRow row = dtTOT.NewCoutTOTRow();

        //    for (int j = 0; j < drSource.Table.Columns.Count; j++)
        //    {
        //        if (drSource[j] != null)
        //        {
        //            row[j] = drSource[j];
        //        } else
        //        {
        //            row[j] = null;
        //        }
        //    }

        //    dtTOT.AddCoutTOTRow(row);
        //}
        //Application.DoEvents();
        //    }
        //} catch (Exception)
        //{
        //}
A: 

On Sql Server 2005 and up, you can create a materialized view of the aggregate values and dramatically speed up the performance.

look at Improving Performance with SQL Server 2005 Indexed Views

KM
I only have read-only access to the server
Nigol
`Also I do not have write access to the SQL server (2005), because the server is maintained by the company that created our MRP program. Although I could always ask support to add a view to the server.`
KM
Thanks, I am just checking my options
Nigol
thinking about it, I do not know if a view would change things, because my objective if to go "back in time" and see the cost a particular job at a specified date. SO I cannot group the cost by job, I would still have to be a record for each day at least and for each type of cost.
Nigol