-1

LINQ クエリでクエリ結果を確認し、ステートメントを終了します。データベースには約 600k のデータがあります。以下は、LINQ クエリと if ステートメントです。

 var feetypelist = from feetype in dbDataContext.tbl_fee_types
                          orderby feetype.seq
                          select feetype.id;

        foreach (var fty in feetypelist)
        {
            var checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                  where fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
                                  orderby fee.seq
                                  select fee;

            if (checkFeeCharges.Count() == 0)
            {
                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                  where fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
                                  && fee.country == country
                                  orderby fee.seq
                                  select fee;
            }

            if (checkFeeCharges.Count() == 0)
            {
                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                  where fee.site_id == siteId && fee.country == country && 
                                  ((fee.arr == arr && fee.dep == dep) || (fee.arr.Equals("DOM") && fee.dep.Equals("DOM")) ||
                                  (fee.arr.Equals("*") && fee.dep == dep) || (fee.arr == arr &&  fee.dep.Equals("*")))
                                  && fee.feetypeid == fty
                                  orderby fee.seq
                                  select fee;

                if (checkFeeCharges.Count() == 0)
                {
                    var country_route = from route in dbDataContext.tbl_country_routes
                                        where route.origin_airport_cd == arr && route.destination_airport_cd == dep
                                        select route;

                    if (country_route.Count() >= 1)
                    {
                        foreach (var c in country_route)
                        {
                            if (c.air_asiax == 'Y')
                            {
                                //con_flight = "Y";
                                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                                  where fee.site_id == siteId && fee.country == country &&
                                                  ((fee.arr == "AAX" && fee.dep == "AAX") || (fee.arr == "*" && fee.dep == dep) ||
                                                  (fee.arr == arr && fee.dep == "*")) && fee.feetypeid == fty
                                                  orderby fee.seq
                                                  select fee;

                                if (checkFeeCharges.Count() == 0)
                                {
                                    checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                                      where fee.site_id == siteId && fee.country == country &&
                                                      ((fee.arr == arr && fee.dep == dep) || (fee.arr == "INT" && fee.dep == "INT") ||
                                                      (fee.arr == "*" && fee.dep == dep) || (fee.arr == arr && fee.dep == "*") ||
                                                      (fee.arr == country && fee.dep == country)) &&
                                                      fee.feetypeid == fty
                                                      orderby fee.seq
                                                      select fee;
                                }
                            }
                            else
                            {
                                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                                  where fee.site_id == siteId && fee.country == country &&
                                                  ((fee.arr == arr && fee.dep == dep) || (fee.arr == "INT" && fee.dep == "INT") ||
                                                  (fee.arr == "*" && fee.dep == dep) || (fee.arr == arr && fee.dep == "*") ||
                                                  (fee.arr == country && fee.dep == country)) &&
                                                  fee.feetypeid == fty
                                                  orderby fee.seq
                                                  select fee;
                            }

                        }
                    }
                    else
                    {
                        checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                          where fee.site_id == siteId && fee.country == country &&
                                          ((fee.arr == arr && fee.dep == dep) || (fee.arr == "INT" && fee.dep == "INT") ||
                                          (fee.arr == "*" && fee.dep == dep) || (fee.arr == arr && fee.dep == "*")) &&
                                          fee.feetypeid == fty
                                          orderby fee.seq
                                          select fee;
                    }
                }
            }

            if (checkFeeCharges.Count() == 0)
            {
                checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                                  where fee.site_id == siteId && fee.country == country &&
                                  ((fee.arr == arr && fee.dep == dep) || (fee.arr == "INT" && fee.dep == "INT") ||
                                  (fee.arr == "*" && fee.dep == dep) || (fee.arr == arr && fee.dep == "*")) &&
                                  fee.feetypeid == fty
                                  orderby fee.seq
                                  select fee;
            }

クエリの実行には時間がかかります。このクエリを最適化する方法を考えてください。

json リクエストを返す

if (checkFeeCharges.Any())
            {
                List<FeeAndChargesModel_Fee_Schedule> feeTable = new List<FeeAndChargesModel_Fee_Schedule>();
                foreach (var p in checkFeeCharges)
                {
                    feeTable.Add(
                        new FeeAndChargesModel_Fee_Schedule()
                        {
                            arr = FlightScheduleAPIController.GetCountryName(arr, siteId),
                            dep = FlightScheduleAPIController.GetCountryName(dep, siteId), 
                            country = p.country,
                            feedesc = p.feedesc,
                            feetype = p.feetype,
                            currency = p.currency,
                            value = p.value,
                            remark = p.remark
                        }
                    );
                    label = p.feetype;


                }

                mainJson.Add(
                        new FeeAndChargesModel_Main
                        {
                            label = label,
                            con_flight = FlightScheduleAPIController.GetCountryName(GetConnectingFlight(dep, arr), siteId),
                            details = feeTable
                        }
                        );
            }
        }

        return mainJson;
4

2 に答える 2

1

このコードは非常に読みにくいですが、アドバイスをしましょう。

最初に気付くのは、最初の sql ステートメントが実行されることです。

var checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                              where fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
                              orderby fee.seq
                              select fee;

何も返さない場合

        if (checkFeeCharges.Count() == 0)
        {

最初のものよりも具体的なSQLクエリを実行します。すべて同じ AND ステートメント + 別のステートメントがあります。最初のクエリが何も返さない場合、2 番目のクエリが何も返さないことが期待されます (すべてが一定です)。もしそうなら、なぜそれをするのですか?

            checkFeeCharges = from fee in dbDataContext.tbl_fee_schedules
                              where fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
                              && fee.country == country
                              orderby fee.seq
                              select fee;
        }

個人的には、次のことを理解したり解決したりしようとします

1 予想される結果セットのサイズはどのくらいですか? また、「少数」のレコードを取得して、これらをメモリ内で処理できますか? 結果セットが時間の経過とともに大きくなるかどうか、およびその最小、最大タイプの境界を理解する必要があります。

2 このクエリをより簡単かつ効率的にするために使用するコードをリファクタリングできる、より優れたデータベース構造はありますか。

3 このクエリを実際に最適化できるようにするには、最初にこれを直接 sql に記述し、explain を使用して、sql データベースが何を行っているか、どのインデックスが使用されているか、返される結果セットのサイズを正確に理解できるようにします。各クエリで。

. また、多くのクエリを 1 つの式に組み合わせることができるはずだとも考えています。

これはおそらく正確ではありませんが、デモンストレーションとしては問題ないはずです

from fee in dbDataContext.tbl_fee_schedules
where (fee.arr == arr && fee.dep == dep && fee.feetypeid == fty && fee.site_id == siteId
    && fee.country == country) || (fee.site_id == siteId && fee.country == country &&
                                              ((fee.arr == "AAX" && fee.dep == "AAX") || (fee.arr == "*" && fee.dep == dep) ||
                                              (fee.arr == arr && fee.dep == "*")) && fee.feetypeid == fty)
|| ( ..... ) | ( .... )

私がそこに見ることができることから、いくつかの結合またはサブ選択が必要になるため、SQL内でそれを試みるのが最も速いでしょう. また、診断に役立つ可能性がある多くの linq2sql/ORM プロファイリング ツールがあります。

于 2013-04-17T05:25:29.533 に答える
0

ここには多くの重複があるため、これを最適化する方法を伝えるのは困難です。それを減らすことから始めたいと思います。

変更すべき明らかな点の 1 つは次のとおりです。

if (checkFeeCharges.Count() == 0)

これにより、呼び出すたびにクエリ全体が列挙されます。同じことをチェックするためのはるかに安価な方法:

if (!checkFeeCharges.Any())

これにより、クエリから 1 つの結果のみが列挙され、それが空かどうかが判断されます。

于 2013-04-17T04:14:29.670 に答える