এসকিউএল সার্ভার 2016-এ সাবস্ক্রিং () ধারণ করে এমন পূর্বাভাস নিয়ে অনুমানের পরিবর্তনগুলি?


13

এসকিউএল সার্ভার ২০১ in-এ পরিবর্তনগুলি সম্পর্কে কোনও ডকুমেন্টেশন বা গবেষণা আছে কীভাবে সাবস্ক্রিং () বা অন্যান্য স্ট্রিং ফাংশনযুক্ত পূর্বাভাসগুলির জন্য কার্ডিনালিটির অনুমান করা হয়?

আমি জিজ্ঞাসা করার কারণটি হ'ল আমি এমন একটি ক্যোয়ারীর দিকে চেয়েছিলাম যার পারফরম্যান্সটি সামঞ্জস্যতা মোড ১৩০ এ অবনমিত হয়েছিল এবং কারণটি ছিল সাবস্ক্রিং () -এ কল থাকা কোনও WHWEE ধারাটির সাথে মিল থাকা সারিগুলির সংখ্যার অনুমানের পরিবর্তনের সাথে সম্পর্কিত। আমি একটি ক্যোয়ারী পুনর্লিখনের মাধ্যমে সমস্যাটি সংশোধন করেছি, তবে ভাবছি যে এসকিউএল সার্ভার ২০১ 2016-এ এই অঞ্চলে পরিবর্তনগুলি সম্পর্কে যে কোনও ডকুমেন্টেশন সম্পর্কে কেউ সচেতন কিনা।

ডেমো কোডটি নীচে। এই পরীক্ষার ক্ষেত্রে অনুমানগুলি খুব কাছাকাছি থাকে তবে তথ্যের উপর নির্ভর করে নির্ভুলতা পরিবর্তিত হয়।

পরীক্ষার ক্ষেত্রে, কমপ্যাট স্তর 120 এ, এসকিউএল সার্ভারটি অনুমানের জন্য হিস্টোগ্রাম ব্যবহার করছে বলে মনে হয়, অন্যদিকে কম্পাট স্তরের ১৩০ এসকিউএল সার্ভার টেবিলের ম্যাচগুলির একটি নির্দিষ্ট 10% নির্ধারণ করে বলে মনে হচ্ছে।

CREATE DATABASE MyStringTestDB;
GO
USE MyStringTestDB;
GO
DROP TABLE IF EXISTS dbo.StringTest;
CREATE TABLE dbo.StringTest ( [TheString] varchar(15) );
GO
INSERT INTO dbo.StringTest
VALUES
( 'Y5_CLV' );
INSERT INTO dbo.StringTest
VALUES
( 'Y5_EG3' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_NE' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_PQT' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_T2V' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_TT4' );
INSERT INTO dbo.StringTest
VALUES
( 'ZY_ZKK' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_LW6' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_QO3' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_TZ7' );
INSERT INTO dbo.StringTest
VALUES
( 'ZZ_UZZ' );

CREATE CLUSTERED INDEX IX_Clustered ON dbo.StringTest (TheString);

/* 
Uses fixed % for estimate; 1.1 rows estimated in this case.
    Plan for computation:
        CSelCalcFixedFilter (0.1) <----
            Selectivity: 0.1
*/
ALTER DATABASE MyStringTestDB SET compatibility_level = 130;
GO
SELECT * 
FROM dbo.StringTest 
WHERE SUBSTRING(TheString, 1, CHARINDEX('_',TheString) - 1) = 'ZZ'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);

/* 
Uses histogram to get estimate of 1
 CSelCalcPointPredsFreqBased <----
      Distinct value calculation:
          CDVCPlanLeaf
              0 Multi-Column Stats, 1 Single-Column Stats, 0 Guesses
      Individual selectivity calculations:
          (none)
    Loaded histogram for column QCOL: [DBA].[dbo].[StringTest].TheString from stats with id 1
*/
ALTER DATABASE MyStringTestDB SET compatibility_level = 120;
GO
SELECT * 
FROM dbo.StringTest 
WHERE SUBSTRING(TheString, 1, CHARINDEX('_',TheString) - 1) = 'ZZ'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);

/*
-- Simpler rewrite; works fine in both compat levels and gets better estimate.
SELECT * 
FROM dbo.StringTest 
WHERE TheString LIKE 'ZZ[_]%'
OPTION (QUERYTRACEON 2363, QUERYTRACEON 3604);
*/

1
নির্দিষ্ট প্রশ্ন সম্পর্কে নিশ্চিত নয়, তবে Y5_EG3স্ট্রিংগুলি যদি কেবল কোড এবং সর্বদা উচ্চ-কেস হয় তবে আপনি বাইনারি কোলেশন নির্দিষ্ট করার চেষ্টা করতে পারেন - Latin1_General_100_BIN2- ফিল্টারিংয়ের ক্রিয়ায় গতি বাড়ানো উচিত। শুধু যোগ COLLATE Latin1_General_100_BIN2করতে CREATE TABLEমাত্র পর বিবৃতি varchar(15)। আমি এটি দেখতে আগ্রহী হব যে এটি পরিকল্পনা জেনারেশন / অনুমানকেও প্রভাবিত করে কিনা।
সলোমন রুটজকি

উত্তর:


8

আমি কোনও ডকুমেন্টেশন সম্পর্কে সচেতন নই। আমি এটি সন্ধান করেছি এবং কিছু পর্যবেক্ষণ করেছি তবে এটি কোনও মন্তব্যের জন্য দীর্ঘ।

10% অনুমান সর্বদা হ্রাস হয় না। নিচের উদাহরণটি ধরুন।

TRUNCATE TABLE dbo.StringTest

INSERT INTO dbo.StringTest
SELECT TOP (1000000) 'ZZ_' + LEFT(NEWID(), 12)
FROM   master..spt_values v1,
       master..spt_values v2;

এবং WHEREআপনার প্রশ্নের ধারা।

WHERE SUBSTRING(TheString, 1, CHARINDEX('_',TheString) - 1) = 'ZZ'

সারণীতে এক মিলিয়ন সারি রয়েছে। এঁরা সকলেই মিলে icate সংক্ষিপ্ত স্তরের ১৩০ এর অধীনে ১০% অনুমানটি এক হাজারের অনুমান করে। 120 এর নিচে আনুমানিক সারিগুলি 1.03913।

120 টি আচরণ হিস্টোগ্রাম ব্যবহার করে তবে কেবল স্বতন্ত্র সারিগুলির সংখ্যা পেতে। আমার ক্ষেত্রে ঘনত্বের ভেক্টরটি 1.039131E-06 দেখায় এবং আনুমানিক সারি গণনা পেতে এটি টেবিল কার্ডিনালিটি দ্বারা গুণিত হয়। মানগুলির সমস্তই আসলে পৃথক তবে সবগুলি প্রাকটিকের সাথে মেলে।

query_optimizer_estimate_cardinalityবর্ধিত ইভেন্টটি সন্ধান করা দেখায় যে ১৩০ এর নীচে দুটি ভিন্ন <StatsCollection Name="CStCollFilter"ইভেন্ট রয়েছে। প্রথমটির অনুমান 100,000। দ্বিতীয়টি হিস্টোগ্রাম লোড করে এবং 1.04 অনুমানের জন্য CSelCalcPointPredsFreqBased / DisinctCountCalculator ব্যবহার করে। এই দ্বিতীয় ফলাফলটি অব্যবহৃত প্রদর্শিত হবে।

আপনি যে আচরণটি পর্যবেক্ষণ করেছেন তা ধারাবাহিকভাবে ১৩০ এ প্রয়োগ করা হয় না। আমি এটি যোগ ORDER BY TheStringকরার জন্য ১৩০ অনুমানকারীটির স্পষ্ট জয় হিসাবে প্রত্যাশা যোগ করেছি কারণ 120 টি এক সারির জন্য মেমরি অনুদানের সাথে লড়াই করে তবে এই সামান্য পরিবর্তনটি আনুমানিক সারিগুলিকে নীচে আনতে যথেষ্ট ছিল 130 কেসেও 1.03913।

যোগ OPTION (QUERYRULEOFF SelectToFilter)করা অনুমানটিকে সাজানোর মধ্যে ১০,০০,০০০ এ রূপান্তরিত করে কিন্তু মেমরি অনুদানটি বৃদ্ধি পায় না এবং সাজানোর ফলাফলটি নির্ধারণ করা সারণীতে স্বতন্ত্র মানগুলির উপর নির্ভরশীল।

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

অনুরূপভাবে সমান্তরালতার জন্য ব্যয়ের প্রান্তকে ট্যুইকড করা যাতে কোয়েরিটি একটি সমান্তরাল পরিকল্পনা পায় তত সংখ্যায় ফিরে যাওয়ার জন্য 130 ক্ষেত্রে যথেষ্ট ছিল। যোগ QUERYTRACEON 8757করাও কম অনুমানের কারণ হয়। দেখে মনে হচ্ছে যে 10% অনুমানটি কেবল তুচ্ছ পরিকল্পনার জন্যই ধরে রাখা হয়।

আপনার প্রস্তাবিত পুনর্লিখন দিয়ে

WHERE TheString LIKE 'ZZ[_]%'

উভয়কেই অনেক উচ্চতর অনুমান দেখায়। এর জন্য আউটপুট হয়

  CSelCalcTrieBased

      Column: QCOL: [MyStringTestDB].[dbo].[StringTest].TheString

এটি চেষ্টা করে দেখানো হচ্ছে । এ সম্পর্কে আরও তথ্য এখানে ঠিক উপরে স্ট্রিং সংক্ষিপ্তসার পরিসংখ্যান বিভাগে ।

এটি আপনার মূল ক্যোয়ারির মতো নয়। হিসাবে এখন প্রথম উদাহরণটি _সর্বদা গতিশীলরূপে অনুসন্ধানের চেয়ে তৃতীয় চরিত্র হিসাবে ধরে নেওয়া হয়।

যদি এই অনুমানটি আপনার মূল ক্যোয়ারিতে হার্ডকোড করা থাকে

 WHERE SUBSTRING(TheString, 1, 3) = 'ZZ_'

অনুমানের পদ্ধতিতে পরিবর্তিত হয় CSelCalcHistogramComparison(INTERVAL)এবং আনুমানিক সারিগুলি নির্ভুল হয়ে যায়।

এটি এটিকে একটি ব্যাপ্তিতে রূপান্তর করতে সক্ষম

WHERE TheString >=  'ZZ_' AND TheString < ???

এবং সেই ব্যাপ্তির মানগুলির সাথে সারিগুলির সংখ্যা অনুমান করতে হিস্টোগ্রামটি ব্যবহার করুন।

এটি তবে কেবল কার্ডিনালিটি অনুমানের ক্ষেত্রে প্রযোজ্য। LIKEএটি রানটাইমের সময় সীমাবদ্ধ সীমা ব্যবহার করতে পারে বলে এটি পছন্দনীয়। SUBSTRING(TheString, 1, 3)বা LEFT(TheString, 3)পারে না

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