বিভিন্ন টেবিল থেকে অর্ডার দিয়ে শীর্ষ 1 নির্বাচন করার সময় কীভাবে সূচীকরণ দর্শন সেট আপ করবেন


11

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

    -- +++ THE QUERY THAT I WANT TO IMPROVE PERFORMANCE-WISE +++

    SELECT TOP 1 *
    FROM    dbo.TB_test1 t1
            INNER JOIN dbo.TB_test2 t2 ON t1.PK_ID1 = t2.FK_ID1
    ORDER BY t1.somethingelse1
           ,t2.somethingelse2;


    GO

টেবিল সেটআপটি নিম্নরূপ:

  • দুটি টেবিল
  • তারা উপরের ক্যোয়ারী দ্বারা একটি অভ্যন্তরীণ যোগদান দ্বারা যোগদান করা হয়
  • এবং প্রথমটি থেকে একটি কলাম এবং তারপরে কোয়েরিতে দ্বিতীয় টেবিল থেকে একটি কলাম দ্বারা অর্ডার করা হয়েছে; কেবল শীর্ষ 1 টি নির্বাচিত হয়েছে
  • (নীচের স্ক্রিপ্টে পরীক্ষার ডেটা উত্পন্ন করার জন্য কিছু লাইন রয়েছে, কেবল যদি সমস্যাটি পুনরুত্পাদন করতে সহায়তা করে)

    -- +++ TABLE SETUP +++
    
    CREATE TABLE [dbo].[TB_test1]
        (
         [PK_ID1] [INT] IDENTITY(1, 1)  NOT NULL
        ,[something1] VARCHAR(40) NOT NULL
        ,[somethingelse1] BIGINT NOT NULL
            CONSTRAINT [PK_TB_test1] PRIMARY KEY CLUSTERED ( [PK_ID1] ASC )
        );
    
    GO
    
    create TABLE [dbo].[TB_test2]
        (
         [PK_ID2] [INT] IDENTITY(1, 1)  NOT NULL
        ,[FK_ID1] [INT] NOT NULL
        ,[something2] VARCHAR(40) NOT NULL
        ,[somethingelse2] BIGINT NOT NULL
            CONSTRAINT [PK_TB_test2] PRIMARY KEY CLUSTERED ( [PK_ID2] ASC )
        );
    
    GO
    
    ALTER TABLE [dbo].[TB_test2]  WITH CHECK ADD  CONSTRAINT [FK_TB_Test1] FOREIGN KEY([FK_ID1])
    REFERENCES [dbo].[TB_test1] ([PK_ID1])
    GO
    
    ALTER TABLE [dbo].[TB_test2] CHECK CONSTRAINT [FK_TB_Test1]
    
    GO
    
    
    -- +++ TABLE DATA GENERATION +++
    
    -- this might not be the quickest way, but it's only to set up test data
    
    INSERT INTO dbo.TB_test1
            ( something1, somethingelse1 )
    VALUES  ( CONVERT(VARCHAR(40), NEWID())  -- something1 - varchar(40)
              ,ISNULL(ABS(CHECKSUM(NewId())) % 92233720368547758078, 1)   -- somethingelse1 - bigint
              )
    
    GO 100000
    
    RAISERROR( 'Finished setting up dbo.TB_test1', 0, 1) WITH NOWAIT    
    
    GO    
    
    INSERT INTO dbo.TB_test2
            ( FK_ID1, something2, somethingelse2 )
    VALUES  ( ISNULL(ABS(CHECKSUM(NewId())) % ((SELECT MAX(PK_ID1) FROM dbo.TB_test1) - 1), 0) + 1 -- FK_ID1 - int
              ,CONVERT(VARCHAR(40), NEWID())  -- something2 - varchar(40)
              ,ISNULL(ABS(CHECKSUM(NewId())) % 92233720368547758078, 1)   -- somethingelse2 - bigint
              )
    
    GO 100000
    
    RAISERROR( 'Finished setting up dbo.TB_test2', 0, 1) WITH NOWAIT          
    
    GO
    

ইনডেক্সড ভিউ সম্ভবত নীচের হিসাবে সংজ্ঞায়িত করা উচিত এবং ফলাফলের শীর্ষ 1 কোয়েরি নীচে। তবে আমার কী সূচিগুলির প্রয়োজন তাই যাতে এই ক্যোয়ারীটি সূচী দর্শন না করে আরও ভাল সম্পাদন করে?

    CREATE VIEW VI_test
    WITH SCHEMABINDING
    AS
        SELECT  t1.PK_ID1
               ,t1.something1
               ,t1.somethingelse1
               ,t2.PK_ID2
               ,t2.FK_ID1
               ,t2.something2
               ,t2.somethingelse2
        FROM    dbo.TB_test1 t1
                INNER JOIN dbo.TB_test2 t2 ON t1.PK_ID1 = t2.FK_ID1


    GO


    SELECT TOP 1 * FROM dbo.VI_test ORDER BY somethingelse1,somethingelse2


    GO

উত্তর:


12

এটিতে আমি যে কোনও সূচি রেখেছি তা এড়িয়ে চলা মনে হচ্ছে

আপনি যদি এসকিউএল সার্ভার এন্টারপ্রাইজ সংস্করণ (বা সমতুল্য, ট্রায়াল এবং বিকাশকারী) ব্যবহার না WITH (NOEXPAND)করেন তবে এটিকে ব্যবহার করার জন্য আপনাকে ভিউ রেফারেন্সে ব্যবহার করতে হবে। প্রকৃতপক্ষে, আপনি যদি এন্টারপ্রাইজ ব্যবহার করে থাকেন তবেও সেই ইঙ্গিতটি ব্যবহার করার ভাল কারণ রয়েছে

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

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

সুতরাং, NOEXPANDটেবিলের ইঙ্গিতটি ব্যবহার করা আপনার প্রধান বিকল্প, তবে আপনি কেবল বেস টেবিল কীগুলি এবং ভিউতে ক্রম অর্ডার করার জন্য প্রয়োজনীয় কলামগুলি বাস্তবায়িত করার বিষয়ে ভাবতে পারেন। সম্মিলিত কী কলামগুলিতে একটি অনন্য ক্লাস্টারড সূচক তৈরি করুন, তারপরে ক্রম কলামগুলিতে একটি পৃথক নন-ক্ল্লাস্টার্ড সূচক।

এটি বস্তুগত দৃশ্যের আকারকে হ্রাস করবে এবং বেস টেবিলের সাথে ভিউটিকে সুসংগত রাখতে যে স্বয়ংক্রিয় আপডেটগুলি করতে হবে তা সীমাবদ্ধ করবে। আপনার জিজ্ঞাসাটি তখন ভিউ থেকে প্রয়োজনীয় ক্রমে শীর্ষ 1 কীগুলি আনার জন্য রচনা করা যেতে পারে (আদর্শভাবে NOEXPAND), তারপরে ভিউ থেকে কীগুলি ব্যবহার করে অবশিষ্ট কোনও কলাম আনতে বেস টেবিলগুলিতে ফিরে যোগদান করুন।

আর একটি প্রকরণ হ'ল অর্ডারিং কলাম এবং টেবিল কীগুলিতে ভিউ ক্লাস্টার করা, তারপরে কীগুলি ব্যবহার করে বেস টেবিল থেকে অ-ভিউ কলামগুলি নিজে হাতে আনতে কোয়েরিটি লিখুন। আপনার জন্য সর্বোত্তম বিকল্পটি বিস্তৃত প্রসঙ্গে নির্ভর করে। সিদ্ধান্ত নেওয়ার একটি ভাল উপায় হ'ল আসল ডেটা এবং কাজের চাপের সাথে এটি পরীক্ষা করা।

বেসিক সমাধান

CREATE VIEW VI_test
WITH SCHEMABINDING
AS
    SELECT
        t1.PK_ID1,
        t1.something1,
        t1.somethingelse1,
        t2.PK_ID2,
        t2.FK_ID1,
        t2.something2,
        t2.somethingelse2
    FROM dbo.TB_test1 t1
    INNER JOIN dbo.TB_test2 t2 
        ON t1.PK_ID1 = t2.FK_ID1;
GO
-- Brute force unique clustered index
CREATE UNIQUE CLUSTERED INDEX cuq 
ON dbo.VI_test 
    (somethingelse1, somethingelse2, PK_ID1, PK_ID2);
GO
SELECT TOP (1) * 
FROM dbo.VI_test WITH (NOEXPAND)
ORDER BY somethingelse1,somethingelse2;

হত্যা পরিকল্পনা:

ব্রুট ফোর্স সূচক

একটি নন-ক্লাস্টারড ইনডেক্স ব্যবহার করা হচ্ছে

-- Minimal unique clustered index
CREATE UNIQUE CLUSTERED INDEX cuq 
ON dbo.VI_test 
    (PK_ID1, PK_ID2)
WITH (DROP_EXISTING = ON);
GO
-- Nonclustered index for ordering
CREATE NONCLUSTERED INDEX ix 
ON dbo.VI_test (somethingelse1, somethingelse2);

হত্যা পরিকল্পনা:

অর্ডার দেওয়ার জন্য অবিচ্ছিন্ন সূচক

এই পরিকল্পনায় একটি লুক রয়েছে, তবে এটি কেবল একটি একক সারি আনতে ব্যবহৃত হয়।

ন্যূনতম সূচী দেখুন

ALTER VIEW VI_test
WITH SCHEMABINDING
AS
    SELECT
        t1.PK_ID1,
        t2.PK_ID2,
        t1.somethingelse1,
        t2.somethingelse2
    FROM dbo.TB_test1 t1
    INNER JOIN dbo.TB_test2 t2 
        ON t1.PK_ID1 = t2.FK_ID1;
GO
-- Unique clustered index
CREATE UNIQUE CLUSTERED INDEX cuq 
ON dbo.VI_test 
    (somethingelse1, somethingelse2, PK_ID1, PK_ID2);

প্রশ্ন:

SELECT TOP (1)
    V.PK_ID1,
    TT1.something1,
    V.somethingelse1,
    V.PK_ID2,
    TT2.FK_ID1,
    TT2.something2,
    V.somethingelse2
FROM dbo.VI_test AS V WITH (NOEXPAND)
JOIN dbo.TB_test1 AS TT1 ON TT1.PK_ID1 = V.PK_ID1
JOIN dbo.TB_test2 AS TT2 ON TT2.PK_ID2 = V.PK_ID2
ORDER BY somethingelse1,somethingelse2;

হত্যা পরিকল্পনা:

চূড়ান্ত ক্যোয়ারী পরিকল্পনা

এটি দেখায় যে টেবিল কীগুলি পুনরুদ্ধার করা হচ্ছে (ক্রমযুক্ত ক্লাস্টারড সূচক থেকে একটি একক সারি আনয়ন) তারপরে বাকী কলামগুলি আনার জন্য বেস টেবিলগুলিতে দুটি একক-সারি লুকআপ রয়েছে।

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