এসকিউএল সার্ভার ২০১৪: কার্ডিনালিটির অনুমানের সাথে বেমানান স্ব স্ব সম্পর্কিত কোনও ব্যাখ্যা?


27

এসকিউএল সার্ভার ২০১৪-তে নিম্নলিখিত কোয়েরি পরিকল্পনাটি বিবেচনা করুন:

এখানে চিত্র বর্ণনা লিখুন

ক্যোয়ারী পরিকল্পনায়, একটি স্ব-যোগদানের ar.fId = ar.fIdমাধ্যমে 1 টি সারির একটি অনুমান পাওয়া যায়। তবে এটি একটি যৌক্তিকভাবে বেমানান অনুমান: arএর 20,608সারি রয়েছে এবং এর একটি মাত্র স্বতন্ত্র মান রয়েছে fId(পরিসংখ্যানগুলিতে নির্ভুলভাবে প্রতিফলিত হয়)। অতএব, এই যোগদানটি সারিগুলি ( ~424MMসারি) এর সম্পূর্ণ ক্রস পণ্য উত্পন্ন করে , যা বেশ কয়েক ঘন্টা ধরে ক্যোয়ারিকে চালিত করে।

এসকিউএল সার্ভার কেন এমন একটি অনুমান নিয়ে আসে যা পরিসংখ্যানগুলির সাথে এতটা বেমানান বলে প্রমাণিত হতে পারে তা বুঝতে আমার খুব কষ্ট হচ্ছে I কোন ধারনা?

প্রাথমিক তদন্ত এবং অতিরিক্ত বিশদ

পলের উত্তরের ভিত্তিতে , এখানে মনে হয় এসকিউএল 2012 এবং এসকিউএল 2014 উভয়ই মূলত জাতীয়তাবাদে যোগদানের অনুমানের জন্য বোধগম্যতার সাথে সহজেই এমন পরিস্থিতি পরিচালনা করতে হবে যেখানে দুটি অভিন্ন হিস্টোগ্রামের তুলনা করা দরকার।

আমি ট্রেস পতাকা 2363 থেকে আউটপুট দিয়ে শুরু করেছি, তবে এটি সহজে বুঝতে পারি না। নীচের স্নিপেটের অর্থ কি এসকিউএল সার্ভার হিস্টোগ্রামের সাথে তুলনা করছে fIdএবং bIdকেবলমাত্র ব্যবহারের সাথে যোগদানের সিলেকটিভিটি অনুমান করতে পারে fId? যদি তা হয় তবে তা অবশ্যই সঠিক হবে না। বা আমি ট্রেস পতাকা আউটপুট ভুল পাঠাচ্ছি?

Plan for computation:
  CSelCalcExpressionComparedToExpression( QCOL: [ar].fId x_cmpEq QCOL: [ar].fId )
Loaded histogram for column QCOL: [ar].bId from stats with id 3
Loaded histogram for column QCOL: [ar].fId from stats with id 1
Selectivity: 0

মনে রাখবেন যে আমি বেশ কয়েকটি কর্মরূপ নিয়ে এসেছি, যা সম্পূর্ণ তিরস্কার স্ক্রিপ্টের অন্তর্ভুক্ত এবং এই ক্যোয়ারীটি মিলি সেকেন্ডে নামিয়ে আনে। এই প্রশ্নটি আচরণটি বোঝার উপর, ভবিষ্যতের অনুসন্ধানগুলিতে কীভাবে এড়াতে হবে এবং মাইক্রোসফ্টের কাছে ফাইল করা উচিত এটি কোনও ত্রুটি কিনা তা নির্ধারণের দিকে দৃষ্টি নিবদ্ধ করে।

এখানে একটি সম্পূর্ণ রেপো স্ক্রিপ্ট , এখানে ট্রেস পতাকা 2363 এর সম্পূর্ণ আউটপুট দেওয়া হয়েছে এবং আপনি পূর্ণ স্ক্রিপ্টটি না খুলে দ্রুত তাদের দিকে নজর দিতে চান এমন ক্ষেত্রে কোয়েরি এবং সারণি সংজ্ঞা এখানে রয়েছে:

WITH cte AS (
    SELECT ar.fId, 
        ar.bId,
        MIN(CONVERT(INT, ar.isT)) AS isT,
        MAX(CONVERT(INT, tcr.isS)) AS isS
    FROM  #SQL2014MinMaxAggregateCardinalityBug_ar ar 
    LEFT OUTER JOIN #SQL2014MinMaxAggregateCardinalityBug_tcr tcr
        ON tcr.rId = 508
        AND tcr.fId = ar.fId
        AND tcr.bId = ar.bId
    GROUP BY ar.fId, ar.bId
)
SELECT s.fId, s.bId, s.isS, t.isS
FROM cte s 
JOIN cte t 
    ON t.fId = s.fId 
    AND t.isT = 1

CREATE TABLE #SQL2014MinMaxAggregateCardinalityBug_ar (
    fId INT NOT NULL,
    bId INT NOT NULL,
    isT BIT NOT NULL
    PRIMARY KEY (fId, bId)
)

CREATE TABLE #SQL2014MinMaxAggregateCardinalityBug_tcr (
    rId INT NOT NULL,
    fId INT NOT NULL,
    bId INT NOT NULL,
    isS BIT NOT NULL
    PRIMARY KEY (rId, fId, bId, isS)
)

উত্তর:


23

এসকিউএল সার্ভার কেন এমন একটি অনুমান নিয়ে আসে যা পরিসংখ্যানগুলির সাথে এতটা বেমানান বলে প্রমাণিত হতে পারে তা বুঝতে আমার খুব কষ্ট হচ্ছে I

দৃঢ়তা

ধারাবাহিকতার কোনও সাধারণ গ্যারান্টি নেই। বিভিন্ন পরিসংখ্যানগত পদ্ধতি ব্যবহার করে বিভিন্ন সময়ে বিভিন্ন (তবে যৌক্তিক সমতুল্য) সাবট্রিতে অনুমানগুলি গণনা করা যেতে পারে।

এই যুক্তিতে কোনও ভুল নেই যে বলে যে এই দুটি অভিন্ন সাবট্রিতে যোগ দেওয়ার জন্য ক্রস পণ্য তৈরি করা উচিত, তবে যুক্তি বাছাইয়ের পছন্দ অন্য যে কোনটির চেয়ে বেশি সুসংবাদযুক্ত বলে সমান কিছুই নেই।

প্রাথমিক অনুমান

আপনার নির্দিষ্ট ক্ষেত্রে, যোগদানের জন্য প্রাথমিক কার্ডিনালিটি অনুমান দুটি অভিন্ন সাবট্রির উপর সম্পাদিত হয় না । সেই সময় গাছের আকার:

  LogOp_Join
     LogOp_GbAgg
        LogOp_LeftOuterJoin
           লগঅপ_গীত টিবিএল: আর
           LogOp_Select
              লগঅপ_গীত টিবিএল: টিসিআর
              ScaOp_Comp x_cmpEq
                 ScaOp_Identifier [tcr] .rId
                 ScaOp_Const মান = 508
           ScaOp_Logical x_lopAnd
              ScaOp_Comp x_cmpEq
                 ScaOp_Identifier [ar] .fId
                 ScaOp_Identifier [tcr] .fId
              ScaOp_Comp x_cmpEq
                 ScaOp_Identifier [আরবি] .বিড
                 ScaOp_Identifier [tcr] .বিড
        AncOp_PrjList 
           AncOp_PrjEl Expr1003 
              ScaOp_AggFunc স্টপম্যাক্স
                 ScaOp_Convers int
                    ScaOp_Identifier [tcr] .ISS
     LogOp_Select
        LogOp_GbAgg
           LogOp_LeftOuterJoin
              লগঅপ_গীত টিবিএল: আর
              LogOp_Select
                 লগঅপ_গীত টিবিএল: টিসিআর
                 ScaOp_Comp x_cmpEq
                    ScaOp_Identifier [tcr] .rId
                    ScaOp_Const মান = 508
              ScaOp_Logical x_lopAnd
                 ScaOp_Comp x_cmpEq
                    ScaOp_Identifier [ar] .fId
                    ScaOp_Identifier [tcr] .fId
                 ScaOp_Comp x_cmpEq
                    ScaOp_Identifier [আরবি] .বিড
                    ScaOp_Identifier [tcr] .বিড
           AncOp_PrjList 
              AncOp_PrjEl Expr1006 
                 ScaOp_AggFunc স্টপমিন
                    ScaOp_Convers int
                       ScaOp_Identifier [আরবি] .আইএসটি
              AncOp_PrjEl Expr1007 
                 ScaOp_AggFunc স্টপম্যাক্স
                    ScaOp_Convers int
                       ScaOp_Identifier [tcr] .ISS
        ScaOp_Comp x_cmpEq
           ScaOp_Identifier Expr1006 
           ScaOp_Const মান = 1
     ScaOp_Comp x_cmpEq
        ScaOp_Identifier QCOL: [ar] .fId
        ScaOp_Identifier QCOL: [ar] .fId

প্রথম যোগদানের ইনপুটটিতে একটি অপ্রক্রোজিত সমষ্টি খুব সহজ সরল হয়ে গেছে, এবং দ্বিতীয় যোগদানের ইনপুটটির নীচে প্রাকটিকটি t.isT = 1ধাক্কা দেওয়া হয়েছে, যেখানে t.isTরয়েছে MIN(CONVERT(INT, ar.isT))। এটি সত্ত্বেও, isTপ্রিডিকেটের জন্য নির্বাচিতকরণ গণনা CSelCalcColumnInIntervalএকটি হিস্টোগ্রামে ব্যবহার করতে সক্ষম :

  CSelCalcColumnInInterval
      কলাম: COL: Expr1006 

QCOL কলামের জন্য হিস্টোগ্রাম লোড করা হয়েছে: [আরবী ভাষায়]। আইডি 3 সহ পরিসংখ্যানগুলি থেকে শুরু করুন

নির্বাচনীকরণ: 4.85248e-005

পরিসংখ্যান সংগ্রহ উত্পন্ন: 
  CStCollFilter (আইডি = 11, কার্ড = 1)
      CStCollGroupBy (আইডি = 10, কার্ড = 20608)
          সিএসটিকোলআউটারজাইন (আইডি = 9, কার্ড = 20608 এক্স_জেট লেফট আউট)
              CStCollBaseTable (আইডি = 3, কার্ড = 20608 টিবিএল: আর)
              সিএসটিকোলফিল্টার (আইডি = 8, কার্ড = 1)
                  CStCollBaseTable (ID = 4, CARD = 28 TBL: tcr)

(সঠিক) প্রত্যাশাটি 20,608 টি সারিটির জন্য এই ভবিষ্যদ্বাণীটির মাধ্যমে 1 টি সারিতে হ্রাস পাবে।

অনুমান যোগদান করুন

অন্যান্য প্রশ্নে যোগ দেওয়া ইনপুট থেকে 20,608 সারি এই এক সারির সাথে কীভাবে মিলবে তা এখন প্রশ্নটি হয়ে ওঠে:

  LogOp_Join
      CStCollGroupBy (আইডি = 7, কার্ড = 20608)
          সিএসটিকোলআউটারজাইন (আইডি = 6, কার্ড = 20608 এক্স_জেট লেফট আউটার)
              ...

      CStCollFilter (আইডি = 11, কার্ড = 1)
          CStCollGroupBy (আইডি = 10, কার্ড = 20608)
              ...

      ScaOp_Comp x_cmpEq
          ScaOp_Identifier QCOL: [ar] .fId
          ScaOp_Identifier QCOL: [ar] .fId

সাধারণভাবে যোগদানের অনুমান করার বিভিন্ন উপায় রয়েছে। আমরা উদাহরণস্বরূপ:

  • প্রতিটি সাবট্রির প্রতিটি প্ল্যান অপারেটরে নতুন হিস্টোগ্রামগুলি আবিষ্কার করুন, তাদের যোগদানের জন্য সারিবদ্ধ করুন (প্রয়োজনীয় হিসাবে ধাপের মানগুলি পৃথক করে) এবং দেখুন কীভাবে তারা মিলছে; অথবা
  • হিস্টোগ্রামগুলির একটি সরল 'মোটা' প্রান্তিককরণ সম্পাদন করুন (ন্যূনতম এবং সর্বাধিক মান ব্যবহার করে, ধাপে নয় ধাপে); অথবা
  • একা জোড় কলামগুলির জন্য পৃথক নির্বাণগুলি গণনা করুন (বেস টেবিল থেকে এবং কোনও ফিল্টারিং ছাড়াই), তারপরে নন-জেন প্রিডিটিক (গুলি) এর সিলেকটিভিটি এফেক্ট যুক্ত করুন।
  • ...

ব্যবহারে কার্ডিনালিটি অনুমানকারী এবং কিছু হিউরিস্টিকের উপর নির্ভর করে, সেগুলির (বা কোনও প্রকরণ) যে কোনওটি ব্যবহার করা যেতে পারে। আরও তথ্যের জন্য এসকিউএল সার্ভার 2014 কার্ডিনালিটির অনুমানের সাহায্যে মাইক্রোসফ্ট হোয়াইট পেপার আপনার প্রশ্নের পরিকল্পনাগুলি অনুকূল করে দেখুন।

বাগ?

এখন, প্রশ্নে উল্লিখিত হিসাবে, এক্ষেত্রে 'সাধারণ' একক-কলামে যোগদান (চালু fId) CSelCalcExpressionComparedToExpressionক্যালকুলেটর ব্যবহার করে :

গণনার পরিকল্পনা:

  CSelCalcExpressionCompareToExpression [ar] .f xd_cmpEq [ar] .fId

QCOL কলামের জন্য হিস্টগ্রাম লোড করা হয়েছে: [আরবি] .বি আইডি 2 সহ পরিসংখ্যানগুলি থেকে আইড করুন
কিউসিওএল কলামের জন্য হিস্টগ্রাম লোড করা হয়েছে: [আরবী ভাষায়]। আইডি 1 সহ পরিসংখ্যানগুলি থেকে আইডি

নির্বাচনীকরণ: 0

এই গণনাটি নির্ধারণ করে যে 1 টি ফিল্টার করা সারি সহ 20,608 সারিগুলিতে যোগদানের একটি শূন্য নির্বাচন রয়েছে: কোনও সারি মেলে না (চূড়ান্ত পরিকল্পনার এক সারি হিসাবে রিপোর্ট করা)। এটা কি ভুল? হ্যাঁ, সম্ভবত এখানে নতুন সিইতে একটি বাগ রয়েছে। যে কেউ তর্ক করতে পারে যে 1 সারিটি সমস্ত সারি বা কোনওটির সাথে মিলবে না, সুতরাং ফলাফলটি যুক্তিযুক্ত হতে পারে তবে অন্যথায় বিশ্বাস করার কারণ রয়েছে।

বিশদটি আসলে কৌতূহলোদ্দীপক, তবে অনুমানের প্রত্যাশাটি fIdফিলিফ্টের সিলেকটিভিটি দ্বারা সংশোধিত, 20608 * 20608 * 4.85248e-005 = 20608সারি দেওয়া সারণী খণ্ডিত হিস্টোগ্রামের উপর ভিত্তি করে করা খুব যুক্তিসঙ্গত।

এই গণনা অনুসরণ করার অর্থ CSelCalcSimpleJoinWithDistinctCountsপরিবর্তে ক্যালকুলেটর ব্যবহার করা CSelCalcExpressionComparedToExpression। এটি করার জন্য কোনও নথিভুক্ত উপায় নেই তবে আপনি যদি আগ্রহী হন তবে আপনি অনাবন্ধিত ট্রেস পতাকা 9479 সক্ষম করতে পারেন:

9479 পরিকল্পনা

নোট করুন চূড়ান্ত যোগদানটি দুটি একক-সারি ইনপুট থেকে 20,608 সারি তৈরি করে, তবে এটি আশ্চর্য হওয়া উচিত নয়। এটি টিএফ 9481 এর অধীনে মূল সিই দ্বারা উত্পাদিত একই পরিকল্পনা।

আমি বিশদটি জটিল এবং (তদন্তে সময়সাপেক্ষ) উল্লেখ করেছি, তবে যতদূর আমি বলতে পারি সমস্যার মূল কারণটি rId = 508শূন্যতার সাথে নির্বাচনী ভবিষ্যতের সাথে সম্পর্কিত । এই শূন্য প্রাক্কলনটি স্বাভাবিক উপায়ে এক সারিতে উত্থাপিত হয়, যা ইনপুট ট্রিটিতে নিম্ন পূর্বাভাসের জন্য অ্যাকাউন্ট হয়ে থাকে (সুতরাং এর জন্য পরিসংখ্যান লোড করা হয় bId) যখন প্রশ্নটিতে যোগ দেওয়ার সময় শূন্য নির্বাচনের অনুমানকে অবদান রাখে বলে মনে হয় ।

বাইরের জোড়কে শূন্য-সারির অভ্যন্তরীণ পার্শ্বের অনুমান রাখতে দেওয়া (এক সারিতে উত্থাপনের পরিবর্তে) (সুতরাং সমস্ত বাহ্যিক সারিগুলি যোগ্য) ক্যালকুলেটরের সাথে একটি 'বাগ-মুক্ত' যোগদানের অনুমান দেয় join আপনি যদি এটি অন্বেষণ করতে আগ্রহী হন, অনির্ধারিত ট্রেস পতাকাটি 9473 (একা):

9473 পরিকল্পনা

এর CSelCalcExpressionComparedToExpressionসাথে জোড় কার্ডিনালিটি অনুমানের আচরণটি অন্য একটি নথিভুক্ত প্রকরণের পতাকা (9494) দিয়ে `` bId` এর জন্য অ্যাকাউন্ট না করেও সংশোধন করা যেতে পারে। আমি এই সমস্ত উল্লেখ করছি কারণ আমি জানি যে এই জাতীয় বিষয়ে আপনার আগ্রহ আছে; তারা সমাধান প্রস্তাব না কারণ। যতক্ষণ না আপনি মাইক্রোসফ্টকে সমস্যাটি প্রতিবেদন করেন এবং তারা এটিকে সম্বোধন করে (বা না), ক্যোয়ারিকে আলাদাভাবে প্রকাশ করা সম্ভবত এগিয়ে যাওয়ার সেরা উপায়। আচরণটি ইচ্ছাকৃত হোক বা না থাকুক না কেন, তারা রিগ্রেশন সম্পর্কে শুনতে আগ্রহী হওয়া উচিত।

পরিশেষে, প্রজনন স্ক্রিপ্টে উল্লিখিত অন্য একটি জিনিসকে পরিষ্কার করার জন্য: প্রশ্ন পরিকল্পনার মধ্যে ফিল্টারটির চূড়ান্ত অবস্থানটি ব্যয়ভিত্তিক অন্বেষণের GbAggAfterJoinSelফলে জন্ডের উপরে সামগ্রিক এবং ফিল্টার সঞ্চারিত হয়, যেহেতু জোড় আউটপুটটির এত ছোট থাকে সারির সংখ্যা. ফিল্টারটি প্রাথমিকভাবে যোগদানের নীচে ছিল, যেমনটি আপনি প্রত্যাশা করেছিলেন।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.