SQL সার্ভার সাধারণ বাইজেকশনে সূচক ব্যবহার করতে ব্যর্থ


11

এটি অন্য কোয়েরি অপটিমাইজার কনড্রাম।

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

আমার একটা সাধারণ টেবিল আছে

CREATE TABLE [dbo].[MyEntities](
  [Id] [uniqueidentifier] NOT NULL,
  [Number] [int] NOT NULL,
  CONSTRAINT [PK_dbo.MyEntities] PRIMARY KEY CLUSTERED ([Id])
)

CREATE NONCLUSTERED INDEX [IX_Number] ON [dbo].[MyEntities] ([Number])

সেখানে একটি সূচক এবং কয়েক হাজার সারি সহ Number0, 1 এবং 2 মানগুলিতে সমানভাবে বিতরণ করা হচ্ছে।

এখন এই ক্যোয়ারী:

SELECT * FROM
    (SELECT
        [Extent1].[Number] AS [Number],
        CASE
        WHEN (0 = [Extent1].[Number]) THEN 'one'
        WHEN (1 = [Extent1].[Number]) THEN 'two'
        WHEN (2 = [Extent1].[Number]) THEN 'three'
        ELSE '?'
        END AS [Name]
        FROM [dbo].[MyEntities] AS [Extent1]
        ) P
WHERE P.Number = 0;

একটি সূচক IX_Numberযেমন আশা করবে তেমন চেষ্টা করে ।

যদি ক্লজটি থাকে

WHERE P.Name = 'one';

তবে এটি একটি স্ক্যান হয়ে যায়।

কেস-ক্লজটি স্পষ্টতই একটি হস্তক্ষেপ, সুতরাং তাত্ত্বিকভাবে দ্বিতীয় ক্যোয়ারী থেকে প্রথম ক্যোয়ারী পরিকল্পনাটি কর্তন করা একটি অপ্টিমাইজেশনের পক্ষে হওয়া উচিত।

এটি নিখুঁত একাডেমিকও নয়: ক্যোয়ারী এনাম মানগুলিকে তাদের নিজ নিজ বন্ধুত্বপূর্ণ নামগুলিতে অনুবাদ করে অনুপ্রাণিত হয়।

আমি এমন কারও কাছ থেকে শুনতে চাই যা জানে যে ক্যোয়ারী অপ্টিমাইজারগুলি (এবং বিশেষত এসকিউএল সার্ভারের মধ্যে একটি) থেকে কী আশা করা যায়: আমি কি খুব বেশি আশা করি?

আমি জিজ্ঞাসা করছিলাম যে এর আগে আমার ক্ষেত্রে কেইসের কিছুটা সামান্য প্রকরণ হঠাৎ করে একটি অপ্টিমাইজেশান প্রকাশিত হবে।

আমি এসকিএল সার্ভার 2016 বিকাশকারী সংস্করণ ব্যবহার করছি।

উত্তর:


18

আমি কি খুব বেশি আশা করি?

হ্যাঁ. কমপক্ষে পণ্যের বর্তমান সংস্করণগুলিতে।

এসকিউএল সার্ভার CASEবিবৃতি আলাদা করে নেবে না এবং এটি আবিষ্কার করতে ইঞ্জিনিয়ারের বিপরীত হবে না যে যদি গণনা কলামের ফলাফল হয় 'one'তবে [Extent1].[Number]অবশ্যই হবে 0

আপনাকে অবশ্যই নিশ্চিত করতে হবে যে আপনি নিজের ভবিষ্যদ্বাণীটি ব্যয়বহুল হিসাবে লিখেছেন। যা প্রায় সর্বদা এটি রূপে জড়িত। basetable_column_name comparison_operator expression

এমনকি ছোটখাটো বিচ্যুতিও ব্যর্থতা ভাঙে।

WHERE P.Number + 0 = 0;

CASEঅভিব্যক্তির চেয়ে সরলকরণের চেয়ে আরও সহজবোধ্য হওয়া সত্ত্বেও একটি সূচক সন্ধানটি ব্যবহার করবে না ।

আপনি যদি একটি স্ট্রিং নামটি অনুসন্ধান করতে চান এবং নাম্বারে সন্ধান পেতে চান তবে আপনার নাম এবং নম্বর সহ একটি ম্যাপিং টেবিলের প্রয়োজন হবে এবং ক্যোয়ারিতে এটিতে যুক্ত হতে পারেন, তবে পরিকল্পনার মানচিত্রের টেবিলে একটি সন্ধান করা যেতে পারে তার পরে একটি সম্পর্কিত সম্পর্কযুক্ত অনুসন্ধান উপর [dbo].[MyEntities]নম্বর থেকে ফিরে প্রথম চাওয়া।


6

কেস স্টেটমেন্ট হিসাবে আপনার এনাম প্রজেক্ট করবেন না। এটিকে এর মতো উত্সযুক্ত টেবিল হিসাবে প্রজেক্ট করুন:

SELECT * FROM
   (SELECT
      [Extent1].[Number] AS [Number],
      enum.Name
   FROM
      [dbo].[MyEntities] AS [Extent1]
      LEFT JOIN (VALUES
         (0, 'one'),
         (1, 'two'),
         (2, 'three')
      ) enum (Number, Name)
         ON Extent1.Number = enum.Number
   ) P
WHERE
   P.Name = 'one';

আমি সন্দেহ করি আপনি আরও ভাল ফলাফল পাবেন। ( ?অনুপস্থিত অবস্থায় আমি নামটি রূপান্তর করি নি কারণ এটি সম্ভবত পারফরম্যান্স লাভের সাথে হস্তক্ষেপ করবে However তবে, টেবিলের WHEREউপরে প্রিকিকেট রাখতে আপনি এই ধারাটি বাইরের ক্যোয়ারির ভিতরে সরিয়ে enumনিতে পারেন, বা আপনি দুটি কলামটি ফিরে আসতে পারেন অভ্যন্তরীণ কোয়েরি, প্রিডিকেটের জন্য একটি এবং প্রদর্শনের জন্য একটি, যেখানে NULLপ্রাক্কলনকারী কোনও হয় যখন এনামের সাথে কোনও মিল নেই))

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

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

এখন, আমি একটি এর একটি গণনার ব্যবহার করছিলাম Identifier বেস ক্লাসের যার অনেকগুলি কংক্রিট সাবক্লাস রয়েছে, তবে এটি সরল ভ্যানিলা এনাম দিয়ে করা সম্ভব হয়নি বলে কোনও কারণ নেই। এখানে একটি উদাহরণ ব্যবহার:

new EnumOrIdentifierProjector<CodeClassOrEnum, PrivateDbDtoObject>(
   _sqlConnector.Connection,
   "dbo.TableName",
   "PrimaryKeyId",
   "NameColumnName",
   dtoObject => dtoObject.PrimaryKeyId,
   dtoObject => dtoObject.NameField,
   EnumerableOfIdentifierOrTypeOfEnum
)
   .Populate();

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

ধারণাটি হ'ল একবার আপনার কাছে এমন একটি টেবিল থাকে যা কেবল একবার প্রারম্ভকালেই লেখা / লেখা হয় যা নির্ভরযোগ্যভাবে সমস্ত এনাম মানগুলি ধারণ করে, আপনি কেবল অন্য কোনও টেবিলের মতো এতে যুক্ত হন, এবং অভিনয়টি ভাল হওয়া উচিত।

আমি আশা করি আপনার উন্নতি করার জন্য এই ধারণাগুলি যথেষ্ট।


হ্যাঁ, আমি এন্টিফ্রেমওয়ার্ক ব্যবহার করি এবং সেখানেই সমাধানটি সর্বোত্তম বিশ্বে হওয়া উচিত। এটি হওয়ার আগে, আপনার পরামর্শটি আমি বিশ্বাস করি যে অন্যতম সেরা কাজের সমাধান।
জন

5

আমি প্রশ্নটি ব্যাখ্যা করি যে আপনি সাধারণভাবে অপ্টিমাইজারের প্রতি আগ্রহী, তবে এসকিউএল সার্ভারের জন্য একটি বিশেষ আগ্রহ নিয়ে। আমি আপনার দৃশ্য db2 LUW V11.1 দিয়ে পরীক্ষা করেছি:

]$ db2 "create table myentities ( id int not null, number int not null )"
]$ db2 "create index ix_number on myentities (number)"
]$ db2 "insert into myentities (id, number) with t(n) as ( values 0 union all select n+1 from t where n<10000) select n, mod(n,3) from t"

ডিবি 2-তে অপ্টিমাইজারটি প্রথম প্রশ্নের সাথে দ্বিতীয় ক্যোয়ারিকে আবারও লিখে দেয়:

Original Statement:
------------------
SELECT 
  * 
FROM 
  (SELECT 
     number,

   CASE 
   WHEN (0 = Number) 
   THEN 'one' 
   WHEN (1 = Number) 
   THEN 'two' 
   WHEN (2 = Number) 
   THEN 'three' 
   ELSE '?' END AS Name 
   FROM 
     MyEntities
  ) P 
WHERE 
  P.name = 'one'


Optimized Statement:
-------------------
SELECT 
  Q1.NUMBER AS "NUMBER",

CASE 
WHEN (0 = Q1.NUMBER) 
THEN 'one' 
WHEN (1 = Q1.NUMBER) 
THEN 'two' 
WHEN (2 = Q1.NUMBER) 
THEN 'three' 
ELSE '?' END AS "NAME" 
FROM 
  LELLE.MYENTITIES AS Q1 
WHERE 
  (0 = Q1.NUMBER)

পরিকল্পনাটি দেখে মনে হচ্ছে:

Access Plan:
-----------
        Total Cost:             33.5483
        Query Degree:           1


      Rows 
     RETURN
     (   1)
      Cost 
       I/O 
       |
      3334 
     IXSCAN
     (   2)
     33.1861 
     4.66713 
       |
      10001 
 INDEX: LELLE   
    IX_NUMBER
       Q1

আমি অন্যান্য অপ্টিমাইজার সম্পর্কে খুব বেশি জানি না, তবে আমি অনুভূতিটি পেয়েছি যে প্রতিযোগীদের মধ্যেও ডিবি 2 অপ্টিমাইজারটিকে বেশ ভাল হিসাবে বিবেচনা করা হয়।


এটা উত্তেজনাপূর্ণ। "অনুকূলিত বিবৃতি" কোথা থেকে এসেছে আপনি কিছুটা আলোকপাত করতে পারেন? ডিবি 2 নিজেই কি আপনাকে এটি ফেরত দেয়? - এছাড়াও, পরিকল্পনা পড়তে আমার সমস্যা হচ্ছে। আমি এটি "আইএক্সএসসিএএন" নিচ্ছি না কি এই ক্ষেত্রে সূচি স্ক্যান মানে না ?
জন

1
আপনি ডিবি 2 কে আপনার পক্ষে একটি বিবৃতি ব্যাখ্যা করতে পারেন। সংগৃহীত তথ্যগুলি টেবিলগুলির একটি সেটে সঞ্চিত থাকে এবং আপনি হয় ভিজ্যুয়াল স্পাইন্ড ব্যবহার করতে পারেন বা এই ক্ষেত্রে ইউটিলিটি db2exfmt (অথবা আপনার নিজের ব্যবহার তৈরি করতে পারেন)। এছাড়াও আপনি কোনও বিবৃতি পর্যবেক্ষণ করতে পারেন এবং পরিকল্পনার আনুমানিক কার্ডিনালিটিকে আসল পরিকল্পনার সাথে তুলনা করতে পারেন। এই পরিকল্পনায় আমরা দেখতে পাচ্ছি যে এটি প্রকৃতপক্ষে একটি ইন্ডেক্সস্ক্যান (আইএক্সএসসিএএন) এবং এই অপারেটরটির আনুমানিক আউটপুট 3334 সারি। এটি কি এসকিউএল সার্ভারে খারাপ? এটি স্টার্টকি এবং স্টপকি জানে তাই এটি কেবলমাত্র ডিবি 2-তে প্রাসঙ্গিক সারিগুলি স্ক্যান করে।
লেনার্ট

সুতরাং এটি স্ক্যানকে যা বলে তা সন্ধানের সাথে জড়িত এবং সত্য কথা বলতে গেলে, এসকিএল সার্ভারের সমতুল্য পরিকল্পনার ব্যাখ্যাগুলি কখনও কখনও এমন কিছু স্ক্যানকে কল করে যা সন্ধানের সাথে জড়িত থাকে এবং অন্য সময় এটি সন্ধান বলে। কী কী তা বোঝার জন্য আমার সর্বদা সারি গণনাটি দেখতে হবে। যেহেতু db2 এর আউটপুটে স্পষ্টভাবে একটি 3334 আছে এটি নিশ্চিত করে যা আমি প্রত্যাশা করছিলাম does অনেক আগ্রহব্যাঞ্জক.
জন

হ্যাঁ, আমি এটি কখনও কখনও বিভ্রান্তিকরও পাই। প্রতিটি অপারেটরকে সত্যিকার অর্থে কী চলছে তা বুঝতে আরও বিশদ তথ্য দেখতে হবে।
লেনার্ট

0

এই বিশেষ ক্যোয়ারিতে, এমনকি একটি CASEবিবৃতি দেওয়া খুব নির্বোধ । আপনি একটি নির্দিষ্ট ক্ষেত্রে ফিল্টার করছেন! সম্ভবত এটি আপনার দেওয়া বিশেষ প্রশ্নের ক্যোয়ারির কেবলমাত্র একটি বিবরণ, তবে যদি তা না হয় তবে সমপরিমাণ ফলাফল পেতে আপনি এই ক্যোয়ারীটি লিখতে পারেন:

SELECT
    [Extent1].[Number] AS [Number],
    'one' AS [Name]
FROM [dbo].[MyEntities] AS [Extent1]
WHERE [Extent1].[Number] = 0;

এটি আপনাকে ঠিক একই ফলাফল সেটটি দেবে এবং যেহেতু আপনি ইতিমধ্যে CASEকোনও বিবৃতিতে শক্ত কোডিং মানগুলি রেখেছেন, আপনি এখানে কোনও রক্ষণাবেক্ষণযোগ্যতা হারাচ্ছেন না।


1
আমি মনে করি আপনি পয়েন্টটি মিস করছেন — এটি ব্যাক-এন্ড কোডবেস থেকে এসকিউএল উত্পন্ন যা তাদের স্ট্রিং উপস্থাপনার মাধ্যমে এনামগুলির সাথে কাজ করে। এসকিউএল প্রজেক্ট করছে এমন কোডটি কোয়েরিতে সহিংসতা করছে। আমি নিশ্চিত যে প্রশ্নকারী যদি নিজে এসকিউএল লিখতেন তবে আরও ভাল কোয়েরি লিখতে সক্ষম হবেন। সুতরাং, মোটেও কোনও CASEবিবৃতি দেওয়া বোকামি নয়, কারণ ওআরএমগুলি এই ধরণের কাজ করে। মূর্খতা হ'ল আপনি সমস্যার এই সাধারণ দিকগুলি চিনতে পারেন নি ... (পরোক্ষভাবে
মস্তিষ্কহীন

@ এরিক এখনও স্টিল ধরণের নির্বোধ, যেহেতু আপনি কেবল এন # এর যে কোনও উপায়ে ধরে ধরে এনুমের সংখ্যার মানটি ব্যবহার করতে পারেন । (একটি মোটামুটি নিরাপদ অনুমান যে আমরা এসকিউএল সার্ভারের সাথে কথা বলছি
given

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

@ এরিক যদি এটি হাস্যকর হয় তবে আপনি কেন এটি করছেন? =) আমি কেবল এটিই উল্লেখ করে উত্তর দিয়েছিলাম যে যদি ব্যবহারের ক্ষেত্রে প্রশ্নটির উদাহরণের মতোই সহজ হয় (যা আমার উত্তরের প্রবন্ধে স্পষ্টভাবে সুনির্দিষ্ট করা হয়), CASEবিবৃতিটি কোনও ত্রুটি ছাড়াই পুরোপুরি নির্মূল করা যেতে পারে। এর অবশ্যই সেখানে অজানা কারণের হতে পারে, কিন্তু তারা অনির্দিষ্ট করছি।
jpmc26

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