কনস্ট্যান্ট স্ক্যান স্পুলিং


14

কয়েক ডজন সারি সহ আমার একটি টেবিল রয়েছে। সরলীকৃত সেটআপ অনুসরণ করা হচ্ছে

CREATE TABLE #data ([Id] int, [Status] int);

INSERT INTO #data
VALUES (100, 1), (101, 2), (102, 3), (103, 2);

এবং আমার কাছে একটি কোয়েরি রয়েছে যা এই টেবিলের সাথে সারণীর মান নির্মিত সারিগুলির (ভেরিয়েবল এবং ধ্রুবকগুলির তৈরি) একটি সেট এর সাথে সংযুক্ত করে

DECLARE @id1 int = 101, @id2 int = 105;

SELECT
    COALESCE(p.[Code], 'X') AS [Code],
    COALESCE(d.[Status], 0) AS [Status]
FROM (VALUES
        (@id1, 'A'),
        (@id2, 'B')
    ) p([Id], [Code])
    FULL JOIN #data d ON d.[Id] = p.[Id];

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

কনস্ট্যান্ট স্ক্যান স্পুলিং

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


উপরোক্ত পরিকল্পনাটি প্রাপ্ত হয়েছিল

মাইক্রোসফ্ট এসকিউএল সার্ভার 2014 (এসপি 2-সিইউ 11) (KB4077063) - 12.0.5579.0 (এক্স 64)


প্রতিক্রিয়া.এজুর.কম
-

উত্তর:


19

অপ্টিমাইজার কেন এখানে স্পুলের পরিচয় দেয়, এটি করার কারণ কী? স্পুলের বাইরে জটিল কিছু নেই।

স্পুলের ওপারের জিনিসটি কোনও সাধারণ টেবিলের রেফারেন্স নয়, যা বাম জোড় / অ্যান্টি আধা সেমিন বিকল্প তৈরি করা হলে কেবল অনুলিপি করা যায়।

এটি দেখতে কিছুটা টেবিলের মতো দেখতে লাগবে (কনস্ট্যান্ট স্ক্যান) তবে অপ্টিমাইজারের UNION ALLকাছে এটি VALUESধারাটির পৃথক সারির একটি ।

অপ্টিমাইজারটি সোর্স সারিগুলিকে স্পুল এবং পুনরায় খেলতে পছন্দ করে এবং পরে স্পুলটিকে কোনও "টেবিল গেট" দিয়ে প্রতিস্থাপন না করে অতিরিক্ত জটিলতা যথেষ্ট। উদাহরণস্বরূপ, পূর্ণ যোগদান থেকে প্রাথমিক রূপান্তরটি এরকম দেখাচ্ছে:

প্রাথমিক পরিকল্পনা

সাধারণ রূপান্তর দ্বারা প্রবর্তিত অতিরিক্ত spools লক্ষ্য করুন। কোনও সাধারণ টেবিলের উপরে থাকা স্পুলগুলি নিয়ম করে পরে পরিষ্কার করা হয় SpoolGetToGet

অপ্টিমাইজারের যদি একটি সম্পর্কিত SpoolConstGetToConstGetনিয়ম থাকে তবে এটি নীতিগতভাবে আপনার ইচ্ছামতো কাজ করতে পারে।

এই ক্ষেত্রে এটি থেকে কীভাবে মুক্তি পাবেন, সম্ভাব্য উপায়গুলি কী কী?

একটি আসল টেবিল (অস্থায়ী বা পরিবর্তনশীল) ব্যবহার করুন, বা সম্পূর্ণ যোগদান থেকে রূপান্তরটি ম্যানুয়ালি লিখুন, উদাহরণস্বরূপ:

WITH 
    p([Id], [Code]) AS
    (
        SELECT @id1, 'A'
        UNION ALL
        SELECT @id2, 'B'
    ),
    FullJoin AS
    (
        SELECT
            p.Code,
            d.[Status]
        FROM p
        LEFT JOIN #data d 
            ON d.[Id] = p.[Id]
        UNION ALL
        SELECT
            NULL,
            D.[Status]
        FROM #data AS D
        WHERE NOT EXISTS
        (
            SELECT *
            FROM p
            WHERE p.Id = D.Id
        )
    )
SELECT
    COALESCE(FullJoin.Code, 'X') AS Code,
    COALESCE(FullJoin.Status, 0) AS [Status]
FROM FullJoin;

ম্যানুয়াল পুনর্লিখনের পরিকল্পনা:

ম্যানুয়াল পুনর্লিখন পরিকল্পনা

মূলটির জন্য 0.0203412 ইউনিটের তুলনায় এটিতে আনুমানিক ব্যয় হয়েছে 0.0067201 ইউনিট।


LogOp_UnionAllএটি রূপান্তরিত গাছের (টিএফ 8605) হিসাবে একটি হিসাবে লক্ষ্য করা যায় । ইন ইনপুট বৃক্ষ (মেমরি 8606) এটি একটি হল LogOp_ConstTableGetরূপান্তরিত বৃক্ষ শো পার্সিং, নিয়মমাফিককরণ, algebrization, বাঁধাই, এবং কিছু অন্যান্য প্রস্তুতিমূলক কাজ পরে অপটিমাইজার অভিব্যক্তি উপাদানের গাছ। ইনপুট বৃক্ষ অস্বীকৃতি সাধারন ফর্ম (NNF ধর্মান্তরিত), রানটাইম ধ্রুবক ধ্বসে, এবং কয়েক অন্যান্য বিট এবং bobs রূপান্তর পর উপাদানের দেখায়। এনএনএফ রূপান্তরটিতে লজিক্যাল ইউনিয়নগুলি ভেঙে ফেলার যুক্তিকে যুক্ত করা হয় এবং অন্যান্য জিনিসগুলির মধ্যে সাধারণ টেবিল পাওয়া যায়।


3

টেবিল স্পুলটি VALUESক্লজে উপস্থিত দুটি সেট টিপলগুলির মধ্যে কেবল একটি টেবিল তৈরি করছে ।

এই মানগুলি প্রথমে একটি টেম্প টেবিলের মধ্যে সন্নিবেশ করে আপনি স্পুলটি নির্মূল করতে পারেন:

DROP TABLE IF EXISTS #data;
CREATE TABLE #data ([Id] int, [Status] int);

INSERT INTO #data
VALUES (100, 1), (101, 2), (102, 3), (103, 2);

DROP TABLE IF EXISTS #p;
CREATE TABLE #p
(
    Id int NOT NULL
    , Code char(1) NOT NULL
);

DECLARE @id1 int = 101, @id2 int = 105;

INSERT INTO #p (Id, Code)
VALUES
        (@id1, 'A'),
        (@id2, 'B');


SELECT
    COALESCE(p.[Code], 'X') AS [Code],
    COALESCE(d.[Status], 0) AS [Status]
FROM #p p
    FULL JOIN #data d ON d.[Id] = p.[Id];

আপনার ক্যোয়ারির কার্যকরকরণ পরিকল্পনার দিকে তাকিয়ে আমরা দেখি আউটপুট তালিকায় দুটি কলাম রয়েছে যা Unionউপসর্গ ব্যবহার করে ; এটি একটি ইঙ্গিত যা স্পুলটি একটি ইউনিয়নের উত্স থেকে একটি টেবিল তৈরি করছে:

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

FULL OUTER JOINSQL সার্ভার মান অ্যাক্সেস করতে প্রয়োজন pযোগদানের প্রতিটি "পাশ" জন্য দুইবার, একবার। একটি স্পুল তৈরি করা ফলস্বরূপ অভ্যন্তরীণ লুপগুলিকে স্পুলযুক্ত ডেটা অ্যাক্সেস করার অনুমতি দেয়।

মজার বিষয় হল, আপনি যদি FULL OUTER JOINa LEFT JOINএবং a এর সাথে প্রতিস্থাপন করেন RIGHT JOINএবং UNIONফলাফলগুলি একসাথে করেন তবে এসকিউএল সার্ভার স্পুল ব্যবহার করে না।

SELECT
    COALESCE(p.[Code], 'X') AS [Code],
    COALESCE(d.[Status], 0) AS [Status]
FROM (VALUES
        (101, 'A'),
        (105, 'B')
    ) p([Id], [Code])
    LEFT JOIN #data d ON d.[Id] = p.[Id]
UNION
SELECT
    COALESCE(p.[Code], 'X') AS [Code],
    COALESCE(d.[Status], 0) AS [Status]
FROM (VALUES
        (101, 'A'),
        (105, 'B')
    ) p([Id], [Code])
    RIGHT JOIN #data d ON d.[Id] = p.[Id];

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

দ্রষ্টব্য, আমি UNIONউপরের ক্যোয়ারীটি ব্যবহার করার পরামর্শ দিচ্ছি না ; বড় আকারের ইনপুটগুলির জন্য, এটি FULL OUTER JOINআপনার ইতিমধ্যে থাকা সাধারণের চেয়ে বেশি কার্যকর নাও হতে পারে।


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