যখন মাইএসকিউএল দিয়ে স্ট্র্যাএইটিT_JOIN ব্যবহার করবেন


88

আমার সবেমাত্র একটি জটিল প্রশ্ন ছিল যার সাথে আমি কাজ করছি এবং এটি চালাতে 8 সেকেন্ড সময় নিচ্ছে। এক্সপ্লেইন একটি অদ্ভুত টেবিল অর্ডার দেখিয়েছিল এবং আমার সূচকগুলি এমনকি সমস্ত ফোর্স ইন্ডেক্সের ইঙ্গিত সহ ব্যবহৃত হচ্ছে না। আমি স্ট্র্যাএইটিT_JOIN জুড়ে এসে কীওয়ার্ডটিতে যোগদান করেছি এবং আমার কিছু INNER JOIN কীওয়ার্ডকে এর সাথে প্রতিস্থাপন করতে শুরু করেছি। আমি যথেষ্ট গতি উন্নতি লক্ষ্য করেছি। অবশেষে আমি এই ক্যোয়ারির জন্য আমার সমস্ত INNER JOIN কীওয়ার্ডগুলিকে স্রেফ STRAIGHT_JOIN দিয়ে প্রতিস্থাপন করেছি এবং এটি এখন .01 সেকেন্ডে চলে।

আমার প্রশ্ন হ'ল আপনি কখন স্ট্রাইটাইটT_জিন ব্যবহার করেন এবং আপনি কখন অন্তর্গত যোগদান করবেন? আপনি যদি ভাল কোয়েরি লিখছেন তবে স্ট্র্যাএইটিT_JOIN ব্যবহার না করার কোনও কারণ আছে কি?

উত্তর:


73

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

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

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


60
এই উত্তরটি কখন ব্যবহার করতে হবে তা ব্যাখ্যা করে না straight_join
পেসারিয়ার

23

থেকে মাইএসকিউএল রেফারেন্স JOIN :

"স্ট্রাইটাইট জাজিন জিনের মতোই, বাম টেবিলটি সর্বদা ডান টেবিলের আগে পড়তে হয়। এটি জয়েন অপটিমাইজার টেবিলগুলিকে ভুল ক্রমে রেখে দেয় এমন (কয়েকটি) ক্ষেত্রে এটি ব্যবহার করা যেতে পারে।"


28
ধন্যবাদ, তবে আমি এটিতে মাইএসকিউএল ম্যানুয়ালটি ইতিমধ্যে পড়েছি। আরও কিছু ব্যাখ্যা জন্য প্রত্যাশী।
গ্রেগ

20

এখানে সম্প্রতি এমন একটি দৃশ্য দেখা গেছে যা কাজের সময়ে এসেছিল।

এ, বি, সি তিনটি সারণী বিবেচনা করুন

এটিতে 3,000 সারি রয়েছে; বিতে 300,000,000 সারি রয়েছে; এবং সিতে 2 হাজার সারি রয়েছে।

বিদেশী কীগুলি সংজ্ঞায়িত করা হয়: বি (এ_আইডি), বি (সি_আইডি)।

ধরুন আপনার কাছে এমন একটি কোয়েরি রয়েছে যা দেখতে এরকম দেখাচ্ছে:

select a.id, c.id
from a
join b on b.a_id = a.id
join c on c.id = b.c_id

আমার অভিজ্ঞতায় মাইএসকিউএল এই ক্ষেত্রে সি -> বি -> এ যেতে পছন্দ করতে পারে। সি এ এর ​​চেয়ে ছোট এবং বি প্রচুর পরিমাণে এবং সেগুলি সমান।

সমস্যাটি হ'ল মাইএসকিউএল প্রয়োজনীয়ভাবে (সিডি এবং বিসি_আইডি) বনাম (এডি এবং বিএআইডি) এর ছেদগুলির আকারটি বিবেচনা করে না। যদি বি এবং সি এর মধ্যে যোগসূত্রটি বি এর মতো অনেকগুলি সারি ফিরে আসে, তবে এটি খুব খারাপ পছন্দ; যদি এ থেকে শুরু করে বি এর সাথে যতগুলি সারিতে ফিল্টার করা হত তবে এটি আরও ভাল পছন্দ হত। straight_joinএই আদেশটি এইভাবে জোর করার জন্য ব্যবহৃত হতে পারে:

select a.id, c.id
from a
straight_join b on b.a_id = a.id
join c on c.id = b.c_id

এখন aঅবশ্যই আগে যোগদান করা উচিত b

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

এটি পরিসংখ্যান যদিও নির্ভর করে। ডেটা বিতরণ পরিবর্তন হলে, গণনা পরিবর্তন হতে পারে। এটি যোগদানের প্রক্রিয়া প্রয়োগের বিশদগুলির উপরও নির্ভর করে।

মাইএসকিউএল-এর জন্য আমি যে সবচেয়ে খারাপ পরিস্থিতি দেখেছি যেগুলি প্রয়োজনীয় straight_joinবা আক্রমণাত্মক সূচক ইঙ্গিত ছাড়াও হালকা ফিল্টারিংয়ের সাথে কঠোরভাবে সাজানো ক্রমে প্রচুর ডেটা পৃষ্ঠাতে উত্পন্ন প্রশ্নগুলি। মাইএসকিউএল যে কোনও ফিল্টারগুলির জন্য সূচকগুলি ব্যবহার করতে পছন্দ করে এবং বিভিন্ন প্রকারের সাথে যোগ দেয়; এটি উপলব্ধি করে কারণ বেশিরভাগ লোকেরা পুরো ডাটাবেসটি বাছাই করার চেষ্টা করছেন না বরং সারিগুলির একটি সীমাবদ্ধ উপসেট রয়েছে যা ক্যোয়ারীর কাছে প্রতিক্রিয়াশীল এবং একটি সীমাবদ্ধ সাবসেটটি বাছাই করা পুরো টেবিলটি ফিল্টারিংয়ের চেয়ে অনেক দ্রুততর, এটি সাজানো বা না কেন তা নয় matter না. এই ক্ষেত্রে, সূচিযুক্ত কলামটি সারণীটির পরে অবিলম্বে সরাসরি যুক্ত হওয়া আমি স্থির জিনিসগুলিতে বাছাই করতে চাই।


সমস্যাটি সমাধান করতে আপনি কীভাবে সরাসরি যোগ যোগ করবেন?
হ্যানেল

@ হানলে straight_joinডান আগে বাম টেবিলটি মূল্যায়ন করে। সুতরাং আপনি যদি A -> B -> Cআমার উদাহরণ থেকে যেতে চান তবে প্রথম joinকীওয়ার্ডটি প্রতিস্থাপন করা যেতে পারে straight_join
ব্যারি কেলি

আহ ঝরঝরে। আপনার উত্তরে উদাহরণ হিসাবে এটি অন্তর্ভুক্ত করা দরকারী হবে :)
হ্যানেল

18

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


11

STRAIGHT_JOINএই ধারাটি ব্যবহার করে আপনি JOINঅর্ডারটি নিয়ন্ত্রণ করতে পারেন : কোন টেবিলটি বাইরের লুপে স্ক্যান করা হয় এবং কোনটি অভ্যন্তরীণ লুপে রয়েছে।


বাইরের লুপ এবং অভ্যন্তরীণ লুপ কী?
ইসতিয়াক আহমেদ

@ ইসতিয়াকআহ্মেড টেবিলগুলি নেস্টেড লুপগুলির সাথে যুক্ত হয় (টেবিল এ থেকে প্রথম সারিটি নেবে এবং লুপ নিক্ষেপ টেবিল বি এর পরে দ্বিতীয় সারিতে নেবে ... এবং আরও কিছু। এখানে টেবিল এ বাইরের লুপে রয়েছে)
অ্যাকাউন্টেন্ট

6

আমি আপনাকে বলব কেন আমাকে স্ট্রাইটাইটT_জিন ব্যবহার করতে হয়েছিল:

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

অতএব আমি বাধ্য হয়ে একজনকে পূর্বের যোগটিকে প্রথমে পড়ার জন্য সরাসরি_ যোগদান করতে বাধ্য করে। এটি মাইএসকিউএলকে এক্সিকিউশন অর্ডার পরিবর্তন করতে বাধা দিয়েছে এবং একটি কবজির মতো কাজ করেছে!


2

আমার সংক্ষিপ্ত অভিজ্ঞতায়, যে পরিস্থিতিগুলির মধ্যে STRAIGHT_JOINআমার জিজ্ঞাসাটি 30 সেকেন্ড থেকে 100 মিলিসেকেন্ডে হ্রাস পেয়েছে তার মধ্যে একটি হ'ল বাস্তবায়নের পরিকল্পনার প্রথম টেবিলটি সেই টেবিলটি ছিল না যে কলামগুলির দ্বারা আদেশ ছিল

-- table sales (45000000) rows
-- table stores (3) rows
SELECT whatever
FROM 
    sales 
    INNER JOIN stores ON sales.storeId = stores.id
ORDER BY sales.date, sales.id 
LIMIT 50;
-- there is an index on (date, id)

অপটিমাইজার আঘাত পছন্দ করে যদি stores প্রথম এটা কারণ হবে Using index; Using temporary; Using filesortকারণ

যদি অর্ডার বা গ্রুপ বাই এর মধ্যে যোগ কাতারে প্রথম টেবিলের বাইরে অন্য টেবিলগুলির কলাম থাকে তবে একটি অস্থায়ী সারণী তৈরি করা হয়।

উৎস

এখানে অপ্টিমাইজারটিকে salesপ্রথমে হিট করতে বলার মাধ্যমে কিছুটা সহায়তা দরকার

sales STRAIGHT_JOIN stores

4
(আমি আপনার উত্তরে শোভিত।)
রিক জেমস

2

দিয়ে আপনার ক্যোয়ারী প্রান্ত তাহলে ORDER BY... LIMIT..., এটা হতে পারে ক্যোয়ারী সূত্রবদ্ধ করতে অনুকূল হতে করছেন মধ্যে অপটিমাইজার প্রতারিত করার LIMIT আগেJOIN

(এই উত্তরটি শুধুমাত্র সম্পর্কিত মূল প্রশ্নের STRAIGHT_JOINক্ষেত্রে প্রযোজ্য নয়, বা এটি সমস্ত ক্ষেত্রেই প্রযোজ্য নয় STRAIGHT_JOIN))

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

SELECT  whatever
    FROM  ( SELECT id FROM sales
                ORDER BY  date, id
                LIMIT  50
          ) AS x
    JOIN  sales   ON sales.id = x.id
    JOIN  stores  ON sales.storeId = stores.id
    ORDER BY  sales.date, sales.id;

মন্তব্য:

  • প্রথমত, 50 টি আইডি আনা হয়। এটি বিশেষত দ্রুত হবে INDEX(date, id)
  • তারপরে যোগদানের জন্য ফিরে আসার জন্য salesআপনাকে কোনও টেম্প টেবিলের আশেপাশে বিনা বাধায় কেবল 50 টি " তড়িঘড়ি " পেতে দেয় ।
  • যেহেতু একটি সাবকিউরিটি সংজ্ঞা অনুসারে, সীমান্তবিহীন, ORDER BYঅবশ্যই বাহ্যিক ক্যোয়ারিতে পুনরাবৃত্তি করতে হবে। (অপ্টিমাইজার প্রকৃতপক্ষে অন্য ধরণের কাজটি এড়াতে কোনও উপায় খুঁজে পেতে পারে))
  • হ্যাঁ, এটা মেসেঞ্জার। তবে এটি সাধারণত দ্রুত হয়।

আমি হিট ব্যবহারের বিরোধিতা করছি কারণ "আজ এটি আরও দ্রুত হলেও এটি আগামীকাল দ্রুত হতে ব্যর্থ হতে পারে।"


0

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

  • সঠিক ক্রমে

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

  • আইডিটি 1 দিয়ে বাড়িয়ে অর্ডারটি মিস করে। 'অতিরিক্ত' ক্ষেত্রটি লক্ষ্য করুন

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

  • স্ট্রেট_জয়েন ব্যবহার করা সমস্যার সমাধান করে

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

মিথ্যা ক্রমটি প্রায় 65 সেকেন্ডের জন্য চলতে থাকে যখন মিলি সেকেন্ডে সোজা_জয়েন রান ব্যবহার করে


-5
--use 120s, 18 million data
    explain SELECT DISTINCT d.taid
    FROM tvassist_recommend_list_everyday_diverse d, tvassist_taid_all t
    WHERE d.taid = t.taid
      AND t.client_version >= '21004007'
      AND t.utdid IS NOT NULL
      AND d.recommend_day = '20170403'
    LIMIT 0, 10000

--use 3.6s repalce by straight join
 explain SELECT DISTINCT d.taid
    FROM tvassist_recommend_list_everyday_diverse d
    STRAIGHT_JOIN 
      tvassist_taid_all t on d.taid = t.taid 
    WHERE 
     t.client_version >= '21004007'
       AND d.recommend_day = '20170403'

      AND t.utdid IS NOT NULL  
    LIMIT 0, 10000

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