কীভাবে ক্যারিটি অনুকূল করবেন


9

আমার কাছে এটির মতো একটি ডাটাবেস কাঠামো রয়েছে,

CREATE TABLE [dbo].[Dispatch](
    [DispatchId] [int] NOT NULL,
    [ContractId] [int] NOT NULL,
    [DispatchDescription] [nvarchar](50) NOT NULL,
CONSTRAINT [PK_Dispatch] PRIMARY KEY CLUSTERED 
(
    [DispatchId] ASC,
    [ContractId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

CREATE TABLE [dbo].[DispatchLink](
    [ContractLink1] [int] NOT NULL,
    [DispatchLink1] [int] NOT NULL,
    [ContractLink2] [int] NOT NULL,
    [DispatchLink2] [int] NOT NULL
) ON [PRIMARY]

GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (1, 1, N'Test')
GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (2, 1, N'Test')
GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (3, 1, N'Test')
GO
INSERT [dbo].[Dispatch] ([DispatchId], [ContractId], [DispatchDescription]) VALUES (4, 1, N'Test')
GO
INSERT [dbo].[DispatchLink] ([ContractLink1], [DispatchLink1], [ContractLink2], [DispatchLink2]) VALUES (1, 1, 1, 2)
GO
INSERT [dbo].[DispatchLink] ([ContractLink1], [DispatchLink1], [ContractLink2], [DispatchLink2]) VALUES (1, 1, 1, 3)
GO
INSERT [dbo].[DispatchLink] ([ContractLink1], [DispatchLink1], [ContractLink2], [DispatchLink2]) VALUES (1, 3, 1, 2)
GO

ডিসপ্যাচলিঙ্ক টেবিলের বিন্দুটি দুটি ডিসপ্যাচ রেকর্ড একসাথে লিঙ্ক করা। উত্তরাধিকারের কারণে আমি আমার প্রেরণের টেবিলে একটি সংযুক্ত প্রাথমিক কীটি ব্যবহার করছি, তাই আমি খুব ব্যথা ছাড়াই এটিকে পরিবর্তন করতে পারি না। এছাড়াও লিঙ্ক টেবিলটি এটি করার সঠিক উপায় নাও হতে পারে? কিন্তু আবার উত্তরাধিকার।

সুতরাং আমার প্রশ্ন, আমি যদি এই কোয়েরি চালাতে

select * from Dispatch d
inner join DispatchLink dl on d.DispatchId = dl.DispatchLink1 and d.ContractId = dl.ContractLink1
or d.DispatchId = dl.DispatchLink2 and d.ContractId = dl.ContractLink2

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

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

আপডেট: উদাহরণস্বরূপ এগুলি হ'ল সূচিগুলির প্রকারগুলি আমি যুক্ত করছি,

CREATE NONCLUSTERED INDEX IDX1 ON DispatchLink (ContractLink1, DispatchLink1)
CREATE NONCLUSTERED INDEX IDX2 ON DispatchLink (ContractLink2, DispatchLink2)
CREATE NONCLUSTERED INDEX IDX3 ON DispatchLink (ContractLink1, DispatchLink1, ContractLink2, DispatchLink2)

সুতরাং এটি সূচকগুলি ব্যবহার করে তবে পুরো সূচক জুড়ে একটি সূচক স্ক্যান করে, তাই 50000 রেকর্ডগুলি সূচকে 50000 রেকর্ড স্ক্যান করে।


DispatchLinkটেবিলে আপনার কি কোনও সূচক আছে ?
ypercubeᵀᴹ

আমি উপরে চেষ্টা করা সূচকগুলি যুক্ত করেছি।
পিটার

আপনার ক্যোয়ারিতে: "ডিসপ্যাচ ডি থেকে অভ্যন্তরীণ যোগ দিন থেকে ডিসপ্যাচলিঙ্ক dl.DispatchId = dl.DispatchLink1 এবং d.ContractId = dl.ContractLink1 বা d.DispatchId = dl.DispatchLink2 এবং d.ContractId = dl ক্লিক করুন "OR" শর্তটি তৈরি করুন এবং প্রতিটিতে "OR" ব্যবহার না করে প্রতিটি 2 টি নির্বাচনী স্টেটমেন্টের ইউনিয়ন দ্বারা প্রতিস্থাপন করুন, পরীক্ষাটিকে যতটা সম্ভব খাঁটি করে তোলার জন্য, "*" এর পরিবর্তে উভয় SELECT এ কেবলমাত্র মূল কলামগুলি ব্যবহার করুন।
NoChance

ধন্যবাদ এসকিউএল কিউই, এটি এমন কিছু যা আমি আগে চেষ্টা করেছি তবে এটি দুর্ভাগ্যজনকভাবে কার্যকর হয়নি।
পিটার

1
আপনার কি অনুলিপি ইস্যুতে একটি সহজ প্রশ্ন থাকতে পারে: ডিসপ্যাচ ডি থেকে অভ্যন্তরীণ ডিসপ্যাচলিংক ডিএল থেকে * নির্বাচন করুন isডিস্পাচআইডি = ডিএল.ডিসপ্যাচলিঙ্ক 1 এবং d.ContractId = dl.ContractLink1 যদি হ্যাঁ, আমরা ডিসপ্যাচলিঙ্কে ডেটা নকল করতে পারি যাতে ফলাফলগুলি এখনও বৈধ থাকে ...
একে

উত্তর:


12

অপ্টিমাইজার অনেকগুলি পরিকল্পনার বিকল্পগুলি বিবেচনা করতে পারে (একাধিক সিক্স সহগুলি সহ) তবে বিযুক্তির জন্য ( ORপূর্বাভাস দেয়) এটি ডিফল্টরূপে সূচক ছেদগুলিতে জড়িত পরিকল্পনাগুলি বিবেচনা করে না। সূচী দেওয়া:

CREATE CLUSTERED INDEX cx 
ON dbo.DispatchLink (DispatchLink1, ContractLink1);

CREATE NONCLUSTERED INDEX nc1 
ON dbo.DispatchLink (DispatchLink2, ContractLink2);

আমরা সূচি সিক্সকে বাধ্য করতে পারি (এসকিউএল সার্ভার ২০০৮ বা তারপরে ধরে):

SELECT * 
FROM dbo.Dispatch AS d
INNER JOIN dbo.DispatchLink AS dl WITH (FORCESEEK) ON 
    (d.DispatchId = dl.DispatchLink1 AND d.ContractId = dl.ContractLink1)
    OR (d.DispatchId = dl.DispatchLink2 AND d.ContractId = dl.ContractLink2);

ফরেক্সেক পরিকল্পনা

আপনার নমুনা তথ্য ব্যবহার করে, স্ক্যান পরিকল্পনার জন্য 0.0068057 এর সাথে তুলনা করে সন্ধানের পরিকল্পনার দাম 0.0332551 ইউনিট :

স্ক্যান পরিকল্পনা

আমরা চেষ্টা করতে পারি এমন সম্ভাব্য ক্যোয়ারী পুনর্লিখন এবং ইঙ্গিতগুলির সব ধরণের রয়েছে। অপ্টিমাইজার মূল পরিকল্পনার জন্য বিবেচনা করে না এমন বিকল্পের প্রচার করতে পুনরায় লেখার একটি উদাহরণ হ'ল:

SELECT * 
FROM dbo.Dispatch AS d
CROSS APPLY
(
    SELECT TOP (1) * FROM
    (
        SELECT * FROM dbo.DispatchLink AS dl
        WHERE dl.DispatchLink1 = d.DispatchId
        AND dl.ContractLink1 = d.ContractId
        UNION ALL
        SELECT * FROM dbo.DispatchLink AS dl
        WHERE dl.DispatchLink2 = d.DispatchId
        AND dl.ContractLink2 = d.ContractId
    ) SQ1
) AS F1;

এই কার্যকর করার পরিকল্পনাটি যদি প্রথমটিতে কোনও মিল খুঁজে পায় তবে এটি দ্বিতীয় সূচকের সন্ধান করবে না:

অ্যাপ্লিকেশন শীর্ষ পরিকল্পনা

এটি ডিফল্ট FORCESEEKপরিকল্পনার চেয়ে কিছুটা ভাল পারফর্ম করতে পারে ।

কোনও নতুন সূচী যুক্ত না করে, আমরা প্রেরণ সারণিতে একটি সন্ধানকে জোর করতে পারি:

SELECT * 
FROM dbo.DispatchLink AS dl
JOIN dbo.Dispatch AS d WITH (FORCESEEK) ON
    (d.DispatchId = dl.DispatchLink1 AND d.ContractId = dl.ContractLink1)
    OR (d.DispatchId = dl.DispatchLink2 AND d.ContractId = dl.ContractLink2);

সন্ধান 2

এটি প্রতিটি টেবিলের মধ্যে কতগুলি সারি রয়েছে তার উপর নির্ভর করে প্রথম উদাহরণের চেয়ে ভাল বা খারাপ হতে পারে। APPLY + TOPউন্নতি এখনো সম্ভব:

SELECT * 
FROM dbo.DispatchLink AS dl
CROSS APPLY
(
    SELECT TOP (1) * FROM
    (
        SELECT * FROM dbo.Dispatch AS d
        WHERE dl.DispatchLink1 = d.DispatchId
        AND dl.ContractLink1 = d.ContractId
        UNION ALL
        SELECT * FROM dbo.Dispatch AS d
        WHERE dl.DispatchLink2 = d.DispatchId
        AND dl.ContractLink2 = d.ContractId
    ) SQ1
) AS F1;

এটি একটি খুব দরকারী উত্তর। আমি আর একটি প্রশ্ন জিজ্ঞাসা করেছি dba.stackexchange.com/questions/23773/analysing-a-query-plan যা আসল ডেটার উপর প্রকৃত ক্যোয়ারী প্ল্যান দেখায় (আমার পরীক্ষার ডেটা নয়)। ক্যোয়ারী পরিকল্পনার অন্তরায় ঠিক কী তা বুঝতে আমার জ্ঞান নেই। সম্ভবত আপনি একবার দেখতে পারেন?
পিটার

এটি সত্যই আকর্ষণীয় কারণ 'ফোর্সেসেক' যুক্ত করা আমার কোয়েরিটি 10 ​​মিনিটের চেয়ে বেশি সময় না নিয়ে 9 সেকেন্ডে চালিত করে। আপডেট পরিসংখ্যান কোন পার্থক্য করে না। কেন অন্য কোয়েরি বিশ্লেষক এটি এত ভুল হয়ে উঠবে?
পিটার

আমি মনে করি আপনি নকশা সম্পর্কে সঠিক। পুনরাবৃত্তি কলামগুলি সম্পর্কে আপনার অর্থ কী? আপনি কীভাবে কোনও টেবিলের কাঠামো ডিজাইন করবেন যা সম্পর্কিত হওয়ার সাথে সাথে দুটি ডিসপ্যাচ রেকর্ডকে যুক্ত করতে হবে? যদিও 'রিয়েল' টেবিলটির নিজস্ব প্রাথমিক কী ক্ষেত্র রয়েছে তবে তা স্পষ্ট করে বলতে গেলে, তবে ডিসপ্যাচে একটি সম্মিলিত কী থাকা হুবহু সহায়তা করে না।
পিটার

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