動的クエリを処理する mvc コントローラー関数を作成しました。うまく機能していますが、より複雑なクエリを使用すると、応答時間が 15 秒も遅くなります。ObjectQuery.ToTraceString を使用して SQL を取得し、データベースに対して実行しました。応答時間は 1 ~ 2 秒で、サーバーが同じクエリに応答するのにかかる時間とは大きく異なります。
これが私のコードです:
public class QueryController : Controller
{
//
// GET: /Query/
Entities1 Context = new Entities1();
public JsonResult Query(
string select,
string table = "Product",
string where = "",
string groupBy = ""
)
IQueryable dataTable;
if (table == "Customer") dataTable = Context.Customers;
else if (table == "Product") dataTable = Context.Products;
else if (table == "Purchase") dataTable = Context.Purchase;
else dataTable = Context.Farms;
if (select == null) return null;
string whereClause = where;
string selectClaus = select;
string groupByClaus = groupBy;
IQueryable queryResults = dataTable;
if (where != "") queryResults = queryResults.Where(whereClause);
if (groupByClaus != "") queryResults = queryResults.GroupBy(groupByClaus, "it");
queryResults = queryResults.Select(selectClaus);
JsonResult result = new JsonResult();
result.Data = queryResults;
result.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
return result;
}
}
このコードは、次のようなリクエストを処理することになっています。
?table=Purchase
&select=new (Customer.First as Name, Product.Id as ProdId)
&where=Category == 5
上記のようなクエリには約 700 ミリ秒かかりますが、もっと複雑なことをしようとすると、クロールまで遅くなります (15 秒):
?table=Purchase
&select=new (
count(true) as Total,
Key.Product as Product,
Key.CustomerRef as CustomerRef,
count(Price > 475) as BigPurchases,
count(PaidFor == false) as UnPaid,
count((Category != null) and (Comments == null) and Returns == null) as NoFeedback)
&groupBy=new (
Product.ProductName as Product,
CustomerRef as CustomerRef
)
特に、ナビゲーション プロパティが問題のようです。これを削除すると、クエリが大幅に高速化されます (3 秒)。
?table=Purchase
&select=new (
count(true) as Total,
Key.Product as Product,
Key.CustomerRef as CustomerRef,
count(Price > 475) as BigPurchases,
count(PaidFor == false) as UnPaid,
count((Category != null) and (Comments == null) and Returns == null) as NoFeedback)
&groupBy=new (
ProductRef as Product,
CustomerRef as CustomerRef
)
私が提供するコードでは、IEnumerable を反復処理するのに時間がかかるようです。データを渡し、基になる MVC コードに必要な変換を行わせます。ただし、自分で反復するか、ToList 関数を使用すると、同様に応答時間が遅くなります。
これらのエンティティを取得するための長い一時停止の原因について、何か考えがある人はいますか?
アップデート
データベースにインデックスを追加して速度を上げましたが、linq でクエリを実行するには、SQL で実行するよりも 20 ~ 30 倍の時間がかかります。