簡體   English   中英

提高LINQ查詢的性能

[英]Improve performance on LINQ Query

當我嘗試循環結果以創建Xelement時,我的linq查詢變慢,我稍后根據XElement處理XSLT。

這是我的代碼

public override XElement Search(SearchCriteria searchCriteria)
    {
        XElement root = new XElement("Root");
        using (ReportOrderLogsDataContext dataContext = DataConnection.GetLinqDataConnection<ReportOrderLogsDataContext>(searchCriteria.GetConnectionString()))
        {
            try
            {


                IQueryable<vw_udisclosedDriverResponsePart> results = from a in dataContext.vw_udisclosedDriverResponseParts
                              where
                                  (a.CreateDt.HasValue &&
                                   a.CreateDt >= Convert.ToDateTime(searchCriteria.BeginDt) &&
                                   a.CreateDt <= Convert.ToDateTime(searchCriteria.EndDt))
                              select a;

                if (!string.IsNullOrEmpty(searchCriteria.AgentNumber))
                {
                    results = results.Where(request => request.LgAgentNumber == searchCriteria.AgentNumber);
                }
                if (!string.IsNullOrEmpty(searchCriteria.AgentTitle))
                {
                    results = results.Where(a => a.LgTitle == searchCriteria.AgentTitle);
                }
                if (!string.IsNullOrEmpty(searchCriteria.QuotePolicyNumber))
                {
                    results = results.Where(a => a.QuotePolicyNumber == searchCriteria.QuotePolicyNumber);
                }
                if (!string.IsNullOrEmpty(searchCriteria.InsuredName))
                {
                    results = results.Where(a => a.LgInsuredName.Contains(searchCriteria.InsuredName));
                }

                foreach (var match in results) // goes slow here, specifically times out before evaluating the first match when results are too large.
                {
                    DateTime date;
                    string strDate = string.Empty;
                    if (DateTime.TryParse(match.CreateDt.ToString(), out date))
                    {
                        strDate = date.ToString("MM/dd/yyyy");
                    }

                    root.Add(new XElement("Record",
                                          new XElement("System", "Not Supported"),
                                          new XElement("Date", strDate),
                                          new XElement("Agent", match.LgAgentNumber),
                                          new XElement("UserId", match.LgUserId),
                                          new XElement("UserTitle", match.LgTitle),
                                          new XElement("QuoteNum", match.QuotePolicyNumber),
                                          new XElement("AddressLine1", match.AddressLine1),
                                          new XElement("AddressLine2", match.AddressLine2),
                                          new XElement("City", match.City),
                                          new XElement("State", match.State),
                                          new XElement("Zip", match.Zip),
                                          new XElement("DriverName", string.Concat(match.GivenName, " ", match.SurName)),
                                          new XElement("DriverLicense", match.LicenseNumber),
                                          new XElement("LicenseState", match.LicenseState)));
                    ;
                }
            }
            catch (Exception es)
            {

                throw es;
            }
        }
        return root;
        // return GetSearchedCriteriaFromStoredPocedure(searchCriteria);
    }

我假設有一種更好的方法將結果對象轉換為XElement。 處理視圖本身只需要大約2秒鍾。 嘗試遍歷結果對象會導致超時,即使未返回許多結果也是如此。

任何幫助,將不勝感激。

謝謝!

-詹姆士

修改7/10/2012

問題不在於linq查詢本身,而是在指定日期范圍時執行視圖。 單獨執行視圖大約需要4-6秒。 當使用較小的日期范圍(07/05/2012 - 07/10/2012)時,視圖大約需要1:30。 有沒有人有任何關於如何提高指定日期范圍的查詢性能的建議。 如果我得到所有結果並通過它們檢查日期,它會更快。

    IQueryable<vw_udisclosedDriverResponsePart> results = from a in dataContext.vw_udisclosedDriverResponseParts select a;

                foreach (var match in results) //results only takes 3 seconds to enumerate, before would timeout
                {
                    // eval search criteria date here.
                }

我可以像上面提到的那樣對它進行編碼,但有沒有人有更好的方法?

數據庫如何運作? 最簡單的測試是運行一個示例查詢 - 一個將從數據庫中檢索所需數據的查詢,只是為了測試數據庫索引和性能 - 因為在99%的情況下,這是導致速度緩慢的原因。

我猜想發生的緩慢是因為

  • 你是從數據庫迭代,而不是檢索前面的所有行,和
  • 你選擇了壞的WHERE條件(你的索引是否正確?)

首先,調用ToList來獲取結果,以確定數據庫中發生的緩慢,而不是XML結構中

if (!string.IsNullOrEmpty(searchCriteria.InsuredName))
{
    //...
}    
var matches = results.ToList();    
foreach (var match in matches) 
{
    //...

假設var matches = results.ToList()非常慢,我會看看WHERE子句中的函數

(a.CreateDt.HasValue &&
a.CreateDt >= Convert.ToDateTime(searchCriteria.BeginDt) &&
a.CreateDt <= Convert.ToDateTime(searchCriteria.EndDt))

檢查它們是否每行都沒有被執行。

如果使用SQL Server,請運行Profiler(在“工具”菜單中)以跟蹤LINQ-to-SQL的SQL。

當然,還要在linq之外進行轉換。 在Linq表達式的運行時期間,條件不會更改。

根據你發布的內容,我做了這個例子:

var begin = Convert.ToDateTime(searchCriteria.BeginDt);
var end = Convert.ToDateTime(searchCriteria.EndDt);

var results = from a in searchList
              where ((a.CreateDt.HasValue &&
                      a.CreateDt >= begin &&
                      a.CreateDt <= end)
                      && (string.IsNullOrEmpty(searchCriteria.AgentNumber) || a.LgAgentNumber == searchCriteria.AgentNumber)
                      && (string.IsNullOrEmpty(searchCriteria.AgentTitle) || a.LgTitle == searchCriteria.AgentTitle)
                      && (string.IsNullOrEmpty(searchCriteria.QuotePolicyNumber) || a.LgTitle == searchCriteria.QuotePolicyNumber)
                      && (string.IsNullOrEmpty(searchCriteria.InsuredName) || a.LgInsuredName.Contains(searchCriteria.InsuredName))
                     )
                        select a;

也許這對你有幫助。

為了測量時間,我使用了以下內容:

var watch = new Stopwatch();
watch.Start();
var arr = results.ToArray();  // force evaluation of linq
watch.Stop();
var elapsed = watch.ElapsedTicks;

似乎已更改的查詢平均速度已快30-40%,但我只是進行了一些運行。

我建議幾個實驗:

一。
放一個

int count = results.Count();

foreach之前,看看這是否需要很長時間。

二。
離開Count()調用,看看foreach是否仍然很慢。 如果速度很快,則表明與db的初始連接速度很慢。

正如其他人所建議的那樣 - 看看你如何在數據庫中查詢執行(實際上在數據庫中輸入,沒有c#)。

您還可以發布SHOW TABLE結果,以便社區可以檢查索引並幫助您進行修復。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM