এসকিউএল সার্ভার কার্ডিনালিটির ইঙ্গিত


14

কীভাবে কোনও এসকিউএল সার্ভার অপ্টিমাইজার (কোনও সংস্করণ) -এর কার্ডিনালিটির অনুমান 'ইনজেক্ট' করা যায়?

অর্থাত্ ওরাকলের কার্ডিনালিটির ইঙ্গিতের মতো কিছু।

আমার অনুপ্রেরণা নিবন্ধটি দ্বারা পরিচালিত হয়, কীভাবে অনুসন্ধানের অপটিমাইজার রয়েছে, সত্যিই? [1] , যেখানে তারা খারাপ পরিকল্পনা নির্বাচনের ক্ষেত্রে কার্ডিনালিটি অনুমানের প্রভাব পরীক্ষা করে। সুতরাং, যদি আমি এসকিউএল সার্ভারকে জটিল প্রশ্নের জন্য নির্ভুলভাবে কার্ডিনালিটিসগুলি 'অনুমান' করতে বাধ্য করতে পারি তবে এটি যথেষ্ট হবে be


[1] লিস, ভিক্টর, ইত্যাদি। "কোয়েরি অপ্টিমাইজার, সত্যিই কত ভাল?"
ভিএলডিবি এন্ডোমেন্ট 9.3 (2015) এর কার্যক্রম: 204-215।

উত্তর:


10

CARDINALITYকৌশলগতভাবে ব্যবহার করে TOPএবং MANY() অ্যাডাম মাচানিক দ্বারা বিকাশকৃত একটি ব্যবহারকারী সংজ্ঞায়িত ফাংশন দিয়ে আপনি ওরাকল এর ইঙ্গিতের অনুরূপ কিছু পেতে পারেন । কয়েকটি উদাহরণের মাধ্যমে কাজ করা যাক। আমি অবাধে উপলভ্য অ্যাডভেঞ্চার ওয়ার্কস ডাটাবেসটি ব্যবহার করছি। মনে করুন যে thনীচের ক্যোয়ারীতে উত্পন্ন সারণী দ্বারা ফিরে আসা সারিগুলির সংখ্যাটি আমার সত্যিই নিয়ন্ত্রণ করতে হবে :

SELECT 
    p.Name
    , th.ProductId
    , th.Quantity
    , th.ActualCost
FROM Production.Product p
INNER JOIN (
    SELECT ProductId, Quantity, ActualCost
    FROM Production.TransactionHistory 
) th ON p.ProductID = th.ProductID;

হিসাবে, আমি 113443 সারিগুলির একটি অনুমান পাই:

শুরু জিজ্ঞাসা

থেকে আমি অনুমান নীচু করার প্রয়োজন হলে thআমি ব্যবহার করতে পারেন TOPসহ OPTIMIZE FORএকটি সারিতে লক্ষ্য নির্ধারণ করবেন ক্যোয়ারী ইঙ্গিত। এটি করার একটি উপায় এখানে:

DECLARE @row_goal BIGINT = 9223372036854775807;
SELECT 
    p.Name
    , th.ProductId
    , th.Quantity
    , th.ActualCost
FROM Production.Product p
INNER JOIN (
    SELECT TOP (@row_goal) ProductId, Quantity, ActualCost
    FROM Production.TransactionHistory 
) th ON p.ProductID = th.ProductID
OPTION (OPTIMIZE FOR (@row_goal = 1));

আমরা দেখতে পারি যে অনুমানটি কেবল 1 সারি:

1 সারি অনুমান

ফলাফল পরিবর্তন এড়াতে আমি @row_goalসবচেয়ে বড় সম্ভাব্য BIGINTমানটিতে সেট করেছি । OPTIMIZE FORক্যোয়ারী ইঙ্গিতটি অপটিমাইজার নির্দেশ যেন ক্যোয়ারী অপ্টিমাইজার করতে@row_goal হয় 1. সমান আমি একই ফলাফল পেতে হবে কিন্তু ক্যোয়ারী ভিন্নভাবে অপ্টিমাইজ করা হবে না।

কার্ডিনালিটির প্রাক্কলন বাড়ানো তাত্পর্যপূর্ণ। আমরা কেবল এর জন্য মানটি বাড়াতে পারি না TOPকারণ অপ্টিমাইজার বুঝতে পারবেন যে এটি পর্যাপ্ত সারিটি ফেরত দেবে না। তবে আমরা MANY()অনুমানটিতে সারি যুক্ত করতে ফাংশনটি ব্যবহার করতে পারি । নোট করুন যে MANY()ফাংশনটি সর্বদা 0 টি সারি ফিরিয়ে আনবে তবে এর থেকে সারি অনুমানটি ইনপুট প্যারামিটারের সাথে পরিবর্তিত হয়। মনে করুন যে আপনাকে 10X দ্বারা উত্পন্ন টেবিল থেকে সারি অনুমানের বৃদ্ধি করতে হবে। এটি সম্পাদনের একটি উপায়:

SELECT 
    p.Name
    , th.ProductId
    , th.Quantity
    , th.ActualCost
FROM Production.Product p
INNER JOIN (
    SELECT TOP (9223372036854775807) ProductId, Quantity, ActualCost
    FROM Production.TransactionHistory 
    LEFT OUTER JOIN dbo.Many(10) AS m ON 1=1
) th ON p.ProductID = th.ProductID;

আমরা দেখতে পাচ্ছি যে অনুমানটি বেস টেবিলের 10X:

10 এক্স ক্যোয়ারী

TOPঅপ্টিমাইজারটিকে টেবিলগুলি চারদিকে নাড়াতে প্রতিরোধ করার জন্য অতিরিক্ত অতিরিক্ত যুক্ত করা হয়েছিল। এটি ছাড়াMANY() ফাংশনটি পরিকল্পনার ভুল জায়গায় প্রয়োগ করা যেতে পারে।

আপনি যদি কোনও ফ্যাক্টর দ্বারা সারিগুলির সংখ্যা কেবল গুণিত করার পরিবর্তে একটি সুনির্দিষ্ট বিবেচনা করতে চান তবে দুটি কৌশল একত্রিত করা সম্ভব। উদাহরণস্বরূপ, ধরা যাক যে আপনার সত্যিকারের 1000000 সারি হতে উত্পন্ন টেবিলের প্রাক্কলন প্রয়োজন। এটি সম্পাদনের একটি উপায়:

DECLARE @row_goal BIGINT = 9223372036854775807;

SELECT 
    p.Name
    , th.ProductId
    , th.Quantity
    , th.ActualCost
FROM Production.Product p
INNER JOIN (
    SELECT TOP (@row_goal) ProductId, Quantity, ActualCost
    FROM Production.TransactionHistory 
    LEFT OUTER JOIN dbo.Many(10) AS m ON
        1=1
) th ON p.ProductID = th.ProductID
OPTION (OPTIMIZE FOR (@row_goal = 1000000));

আমরা দেখতে পাচ্ছি যে অনুমানটি 1000000 সারি:

1 এম সারি

আমার আপনাকে সতর্ক করতে হবে যে এগুলি উন্নত কৌশল যা প্রায়শই ক্যোয়ারী অপ্টিমাইজেশনের জন্য প্রয়োজন হয় না। আপনি যদি আরও জানতে চান তবে আমি অ্যাডাম মাচানিকের উপস্থাপিত রো গোলগুলির ক্ল্যাশ দেখার সুপারিশ করছি।


dbo.Mane ফাংশন

-- By Adam Machanic, reproduced with permission
IF EXISTS (SELECT * FROM sys.objects WHERE name = 'Many' AND OBJECT_SCHEMA_NAME(object_id) = 'dbo')
    DROP FUNCTION dbo.Many
GO
CREATE FUNCTION dbo.Many(@n INT)
RETURNS TABLE AS
RETURN
(
    WITH
    a(x) AS
    (
        SELECT
            *
        FROM
        (
            VALUES
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1),
                (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1), (1)
        ) AS x0(x)
    )
    SELECT TOP(@n)
        1 AS x
    FROM
        a AS a1,
        a AS a2
    WHERE
        a1.x % 2 = 0
)
GO

9

সরাসরি অপ্টিমাইজারে একটি কার্ডিনালিটি অনুমান ইনজেকশন করার কোনও উপায় নেই তবে আপনি কী অর্জন করতে চান তার উপর নির্ভর করে কয়েকটি বিকল্প রয়েছে।

আপনি OPTION (FAST N)সারি লক্ষ্যগুলি উপস্থাপন করতে একটি কোয়েরি ইঙ্গিতটি ব্যবহার করতে পারেন এবং সিটিই বা ইনজেকশনের জন্য সাবকিউরিগুলি ব্যবহার করে আপনার কোয়েরিটি পুনরায় লিখতে পারেনTOP...ORDER BY আপনার এক্সিকিউশন পরিকল্পনার বিভিন্ন অংশে ভিত্তিক সারি লক্ষ্যগুলি , তবে আমি নিশ্চিত না যে আপনি যখন শুরু করবেন তখন আপনার ফলাফলের ক্যোয়ারী কতটা দক্ষ হবে will আরও জটিল নির্মাণ সঙ্গে চারপাশে খেলা।

দেখুন সারি গোল গভীরতা: ইনসাইড অপ্টিমাইজার আরো একটি পুঙ্খানুপুঙ্খ ব্যাখ্যা জন্য।

আপনি যদি অপারেটরগুলিকে প্রভাবিত করতে চান তবে অপ্টিমাইজারটি আপনাকে বেছে নিয়েছে যে আপনার কার্ডিনালটির অনুমানগুলি ইনজেকশনের চেষ্টা করার দরকার নেই তবে আপনি শারীরিক যোগদান অপারেটরদের জোর করতে যেমন OPTION (MERGE JOIN)বা OPTION (HASH JOIN)উদাহরণ ব্যবহার করতে পারেন ।

এই নিবন্ধটি কীভাবে ইঙ্গিতগুলি ব্যবহার করে কোনও পরিকল্পনাকে প্রভাবিত করতে পারে সে সম্পর্কে আরও বিস্তারিতভাবে যায়: ইঙ্গিতগুলি সহ কার্যকরকরণ পরিকল্পনা নিয়ন্ত্রণ করা

আপনি যদি কোনও পরিকল্পনা ঠিক করতে চান তবে আপনি একটি পরিকল্পনা গাইডও ব্যবহার করতে পারেন।

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


প্রাসঙ্গিক মাইক্রোসফ্ট সংযোগের পরামর্শ: xor88 দ্বারা ক্যোয়ারীতে ফিল্টার নির্বাচনের ইঙ্গিত নির্দিষ্ট করার অনুমতি দিন । মাইক্রোসফ্ট এর প্রতিক্রিয়া:

সাহায্য করার জন্য ধন্যবাদ. আমি এর সম্ভাব্য সুবিধা দেখতে পাচ্ছি। সাধারণভাবে আমরা আমাদের স্বয়ংক্রিয় আচরণটি যথাসম্ভব ভাল করার জন্য এবং এই ধরণের ইঙ্গিতটির প্রয়োজনীয়তা এড়াতে কঠোর চেষ্টা করি তবে অবশ্যই আমাদের আরও অনেক ইঙ্গিত রয়েছে। আমরা এটি ভবিষ্যতের মুক্তির জন্য বিবেচনা করব তবে এটি ডেনালি (১১.০) সংস্করণের বাইরে beyond

শুভেচ্ছা,
এরিক হ্যানসন
প্রোগ্রাম ম্যানেজার
এসকিউএল সার্ভার কোয়েরি প্রক্রিয়াজাতকরণ


3

OPTIMIZE FORসংকলনের সময় আপনি প্রকৃত মান (পরামিতি) বা অজানা মান (ভেরিয়েবল) ব্যবহার না করে ইঙ্গিতযুক্ত মানগুলির উপর ভিত্তি করে কার্ডিনালিটির অনুমানকে বাধ্য করার জন্য আপনি এসকিউএল সার্ভার ক্যোয়ারী ইঙ্গিতটি ব্যবহার করতে পারেন । সম্পূর্ণ বিবরণের জন্য এসকিউএল সার্ভার ডকুমেন্টেশনে কোয়েরি ইঙ্গিতগুলি দেখুন ।

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

DECLARE 
      @StartDate datetime = '20150101'
    , @EndDate datetime = '20150102';
SELECT *
FROM dbo.Example
WHERE
    DateColumn BETWEEN  @StartDate AND @EndDate
OPTION(OPTIMIZE FOR(@StartDate = '20100101', @EndDate='20100101'));

একইভাবে, ইঙ্গিতটি পরামিতিগুলির জন্য ব্যবহার করা যেতে পারে যাতে সংকলনের সময় প্রকৃত প্যারামিটার মানগুলির পরিবর্তে হিন্ট করা মানগুলি থেকে পরিসংখ্যানের হিস্টোগ্রামের উপর ভিত্তি করে অনুমান করা যায়।

DECLARE 
      @StartDate datetime = '20150101'
    , @EndDate datetime = '20150102';
EXECUTE sp_executesql N'SELECT *
        FROM dbo.Example
        WHERE
            DateColumn BETWEEN  @StartDate AND @EndDate
        OPTION(OPTIMIZE FOR(@StartDate = ''20100101'', @EndDate=''20100101''));'
    , N'@StartDate datetime, @EndDate datetime'
    , @StartDate = @StartDate
    , @EndDate = @EndDate;

মূল UNKNOWNশব্দটি প্রকৃত প্যারামিটার মান এবং পরিসংখ্যান হিস্টোগ্রামের উপর ভিত্তি করে অনুমানের পরিবর্তে সামগ্রিক গড় কার্ডিনালিটি ব্যবহার করার ইঙ্গিতটিতে আক্ষরিক পরিবর্তে নির্দিষ্ট করা যেতে পারে।

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