বনাম উপ-কোয়েরিতে যোগদান করুন


835

আমি একজন পুরানো স্কুল মাইএসকিউএল ব্যবহারকারী এবং সর্বদা JOINসাব-কোয়েরির চেয়ে বেশি পছন্দ করেছি । তবে আজকাল প্রত্যেকে সাব-কোয়েরি ব্যবহার করে, এবং আমি এটি ঘৃণা করি; কেন জানি না।

আমার মধ্যে কোনও পার্থক্য থাকলে বিচার করার মত তাত্ত্বিক জ্ঞানের অভাব আছে। একটি সাব-কোয়েরি কি হিসাবে ভাল JOINএবং তাই উদ্বেগ করার কিছুই নেই?


23
সাবকিউরিগুলি কখনও কখনও দুর্দান্ত হয়। তারা মাইএসকিউএলে পারফরম্যান্স অনুযায়ী স্তন্যপান করে। এগুলি ব্যবহার করবেন না।
রানিগ

8
আমি সর্বদা এই ছাপের মধ্যে ছিলাম যে সাব-কোয়েরিগুলি স্পষ্টভাবে মৃত্যুদন্ড কার্যকর করা হয়েছিল যেখানে নির্দিষ্ট ডিবি প্রযুক্তিতে পাওয়া যায়।
কেজ্জার

18
সাব-কোয়েরিগুলি সর্বদা স্তন্যপান করে না, বেশ বড় বড় টেবিলগুলির সাথে যোগদানের সময়, পছন্দসই উপায়টি হল সেই বৃহত টেবিল (সারিগুলির সংখ্যা সীমাবদ্ধ করা) থেকে উপ-নির্বাচন করা এবং তারপরে যোগদান করা।
ovais.tariq

136
"আজকাল প্রত্যেকে সাব-কোয়েরি ব্যবহার করে" [উদ্ধৃতি আবশ্যক]
পিসকভর

3
সম্ভাব্য সাথে সম্পর্কিত (যদিও আরো অনেক কিছু নির্দিষ্ট): stackoverflow.com/questions/141278/subqueries-vs-joins/...
লে Brenecki

উত্তর:


190

মাইএসকিউএল ম্যানুয়াল থেকে নেওয়া ( ১৩.২.১০.১১ পুনরায় লেখার সাবকিউরিজগুলি যোগদান হিসাবে ):

একটি বাম [আউটার] যোগদান করা সমতুল্য সাবকিউয়ের চেয়ে দ্রুততর হতে পারে কারণ সার্ভার এটি আরও ভালভাবে অনুকূল করতে সক্ষম হতে পারে - এটি মাইএসকিউএল সার্ভারের সাথে নির্দিষ্ট নয় fact

সুতরাং subqueries তুলনায় ধীর হতে পারে LEFT [OUTER] JOIN, কিন্তু আমার মতে তাদের শক্তি কিছুটা বেশি পঠনযোগ্যতা।


45
@ ব্যবহারকারী 1735921 আইএমও এটি নির্ভর করে ... সাধারণত কোডটির পাঠযোগ্যতা এটি অত্যন্ত গুরুত্বপূর্ণ কারণ এটি পরবর্তী ব্যবস্থাপনার জন্য এটি অত্যন্ত গুরুত্বপুর্ণ ... আসুন ডোনাল্ড নথের বিখ্যাত বক্তব্যটি মনে রাখবেন: "অকালীন অপটিমাইজেশন সকলের মূল প্রোগ্রামিংয়ে অশুভ (বা এর বেশিরভাগ অংশ) " । তবে, স্বাভাবিকভাবেই প্রোগ্রামিংয়ের ক্ষেত্রগুলি রয়েছে যেখানে পারফরম্যান্স
সর্বজনীন

30
আরও জটিল প্রশ্নগুলিতে আমি সাব-কোয়েরির চেয়ে পড়তে অনেক সহজ যোগ পেয়েছি। সাব-কোয়েরিগুলি আমার মাথার নুডলসের বাটিতে পরিণত হয়।
জহরা

6
@ ব্যবহারকারী 1735921 নিশ্চিত, বিশেষত যখন ক্যোয়ারীটি এত জটিল হয়ে যায় যে এটি ভুল কাজ করে এবং আপনি এটি ঠিক করতে একটি দিন ব্যয় করেন ... এর মধ্যে যথারীতি ভারসাম্য রয়েছে।
fabio.sussetto

6
@ ব্যবহারকারী 1735921 শুধুমাত্র যদি পারফরম্যান্সের লাভগুলি ভবিষ্যতে প্রয়োজনীয় রক্ষণাবেক্ষণের সময় বৃদ্ধির জন্য মূল্যবান হয়
জোশুয়া শ্লিচটিং

3
আমার মতামত Joinএবং sub queryপৃথক বাক্য গঠন রয়েছে, সুতরাং পাঠযোগ্যতার সাথে আমরা তুলনা করতে পারি না, উভয় ক্ষেত্রেই আপনি এসকিউএল সিনট্যাক্সে ভাল হিসাবে পঠনযোগ্যতা বেশি থাকে। পারফরম্যান্স আরও গুরুত্বপূর্ণ।
থভাপ্রকাশ স্বামীনাথন

840

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

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

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


105
দুর্দান্ত উত্তর। আমি এটিও যুক্ত করব যে বিকাশকারীরা (যেমন, অপেশাদার লোকেরা) এসকিউএল-তে সর্বদা দক্ষ নয়।
vlvaro González

4
+1 দীর্ঘদিন ধরে এই সমস্যাটির জন্য কিছু যৌক্তিক ব্যাখ্যা খুঁজছেন, এটি কেবলমাত্র আমার কাছে যৌক্তিক বলে মনে হচ্ছে এমন উত্তর
আলী উমাইর

1
@ মার্সেলো ক্যান্টোস, আপনি কি দয়া করে আপনার বক্তব্যটির একটি উদাহরণ দিতে পারেন "এটি व्यावहारिक দিক থেকেও নিরাপদ, যেহেতু বিয়ের বিপক্ষে একাধিক ম্যাচের কারণে আপনাকে এ থেকে নকল তথ্য পাওয়ার বিষয়ে সতর্কতা অবলম্বন করতে হবে না"? আমি এটিকে খুব অন্তর্দৃষ্টিপূর্ণ বলে মনে করি তবে এটি একটি সামান্য বিমূর্ত। ধন্যবাদ।
জিংহুই নিউ

6
@JinghuiNiu যারা গ্রাহকরা ব্যয়বহুল আইটেম কেনা: select custid from cust join bought using (custid) where price > 500। যদি কোনও গ্রাহক একাধিক ব্যয়বহুল আইটেম কিনে তবে আপনি ডাবল-আপ পাবেন। এটি ঠিক করতে select custid from cust where exists (select * from bought where custid = cust.custid and price > 500),। select distinct …পরিবর্তে আপনি ব্যবহার করতে পারেন , তবে এটি অপটিমাইজার বা মূল্যায়নকারীর পক্ষে প্রায়শই বেশি কাজ।
মার্সেলো ক্যান্টোস

1
পছন্দ করুন একটি বাস্তব দৃশ্যে আপনি কাস্টম থেকে কেবল কাস্টড না করে আরও কলামগুলি টানছেন।
মার্সেলো ক্যান্টোস

357

বেশিরভাগ ক্ষেত্রে JOINএস সাব-কোয়েরির চেয়ে দ্রুত এবং সাব-কোয়েরির দ্রুত হওয়া খুব বিরল।

ইন JOINএর RDBMS একটি মৃত্যুদন্ড পরিকল্পনা যা আপনার জিজ্ঞাসার জন্য ভাল তৈরি করতে পারেন এবং পূর্বাভাস দিতে পারি কোন ডেটা প্রক্রিয়া হওয়ার লোড করা উচিত এবং উপ-ক্যোয়ারী যেখানে এটি সব প্রশ্নের চালানো এবং প্রক্রিয়াকরণ করতে তাদের সমস্ত ডেটা লোড করা হবে অসদৃশ সময় বাঁচান, ।

সাব-কোয়েরিতে ভাল জিনিস হ'ল তারা JOINs এর চেয়ে বেশি পঠনযোগ্য : এজন্য বেশিরভাগ নতুন এসকিউএল লোক তাদের পছন্দ করে; এটি সহজ উপায়; তবে যখন পারফরম্যান্সের কথা আসে তখন জিনগুলি বেশিরভাগ ক্ষেত্রেই বেশি ভাল হয় যদিও তাদের পড়া খুব বেশি কঠিন নয়।


14
হ্যাঁ, বেশিরভাগ ডাটাবেসগুলিতে এটি আপনার কোয়েরি বিশ্লেষণ করার সময় সাবউইরিয়াকে যোগ দিয়ে রূপান্তরিত করার জন্য এটি একটি অপ্টিমাইজেশন পদক্ষেপ হিসাবে অন্তর্ভুক্ত করে।
সিনে

16
এই উত্তরটি জিজ্ঞাসা করা প্রশ্নের জন্য কিছুটা সরল। আপনি যেমনটি বলেছেন: নির্দিষ্ট সাবকিউরিগুলি ঠিক আছে এবং কিছু নির্দিষ্ট নয়। উত্তরটি দু'টি আলাদা করতে সত্যই সহায়তা করে না। (এছাড়াও 'খুব বিরল' আপনার ডেটা / অ্যাপের উপর নির্ভর করে)।
অবাস্তব

21
আপনি ডকুমেন্টেশন রেফারেন্স বা পরীক্ষার ফলাফলের সাথে আপনার কোনও পয়েন্ট প্রমাণ করতে পারবেন?
Uğur Güşmüşhan

62
আমি সাব-কোয়েরিতে খুব ভাল অভিজ্ঞতা দিয়েছি যা উপরের ক্যোয়ারির একটি ব্যাক-রেফারেন্স ধারণ করে, বিশেষত যখন এটি 100,000 এর উপরে সারি-গণিতে আসে। জিনিসটি মনে হচ্ছে অদলবদল ফাইলটিতে মেমরির ব্যবহার এবং পেজিং। একটি জোড় একটি খুব বড় পরিমাণে ডেটা উত্পাদন করে, যা মেমরির সাথে খাপ খায় না এবং অদলবদল ফাইলের মধ্যে পৃষ্ঠাযুক্ত করা আবশ্যক। যখনই এটি হয় তখন ছোট সাব-সিলেক্টের ক্যোয়ারী সময়গুলি select * from a where a.x = (select b.x form b where b.id = a.id)যোগদানের তুলনায় অত্যন্ত ছোট। এটি একটি খুব নির্দিষ্ট সমস্যা, তবে কিছু ক্ষেত্রে এটি আপনাকে ঘন্টা থেকে কয়েক মিনিটের মধ্যে নিয়ে আসে।
জুলু

13
আমি ওরাকল এর সাথে অভিজ্ঞ এবং আমি বলতে পারি, আপনার যদি কোনও ফিল্টারিং বা তাদের বাছাই না করে থাকে তবে সাব-কোয়েরিগুলি বড় টেবিলগুলিতে আরও ভাল।
আমির পাশাজাদেহ

130

আপনার ডেটাবেস কীভাবে আপনার ডেটাতে ক্যোয়ারি চালায় তা দেখতে এক্সপ্লেইন ব্যবহার করুন। এই উত্তরে একটি বিশাল "এটি নির্ভরশীল" আছে ...

পোস্টগ্র্রেএসকিউএল একটি সাবউকিকে পুনরায় লিখতে পারে যখন যোগসূত্রে যোগ দিতে পারে বা সাবকোয়ারিতে যোগ দিতে পারে যখন মনে হয় যে এটি অন্যটির চেয়ে দ্রুত is এটি সমস্ত ডেটা, সূচী, পারস্পরিক সম্পর্ক, ডেটার পরিমাণ, কোয়েরি ইত্যাদির উপর নির্ভর করে


6
ঠিক এই কারণেই পোস্টগ্র্যাস্কলটি এত ভাল এবং দরকারী এটি লক্ষ্যটি কী তা বোঝে এবং এটি আরও ভাল বলে মনে করে তার উপর ভিত্তি করে একটি কোয়েরি ঠিক করে দেবে এবং
পোস্টগ্র্যাসকিএল

heww। আমার মনে হয় আমার জন্য অনেকগুলি প্রশ্ন পুনরায় লেখার দরকার নেই! জয়ের জন্য postgresql।
ড্যানিয়েল শিন

77

২০১০ সালে আমি এই প্রশ্নের লেখকের সাথে যোগ দিতাম এবং JOINদৃ strongly়তার সাথে ভোট দিতাম , তবে আরও অনেক অভিজ্ঞতার সাথে (বিশেষত মাইএসকিউএল) আমি বলতে পারি: হ্যাঁ সাবকিউরিজ আরও ভাল হতে পারে। আমি এখানে একাধিক উত্তর পড়েছি; কিছু উল্লিখিত subqueries দ্রুত, কিন্তু এটি একটি ভাল ব্যাখ্যা অভাব। আমি আশা করি আমি এই (খুব) দেরী উত্তরটি সরবরাহ করতে পারি:

সবার আগে, আমি সর্বাধিক গুরুত্বপূর্ণ বলি: উপ-প্রশ্নের বিভিন্ন রূপ রয়েছে

এবং দ্বিতীয় গুরুত্বপূর্ণ বিবৃতি: আকারের বিষয়গুলি

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

নির্বাচন ক্ষেত্রগুলিতে সাব-কোয়েরি

SELECT moo, (SELECT roger FROM wilco WHERE moo = me) AS bar FROM foo

সচেতন হন যে থেকে প্রতিটি ফলাফলের সারির জন্য একটি উপ-ক্যোয়ারী কার্যকর করা হয়েছে foo
সম্ভব হলে এড়িয়ে চলুন; এটি বিশাল ডেটাসেটগুলিতে আপনার ক্যোয়ারীটিকে তীব্রভাবে কমিয়ে দিতে পারে। তবে, সাব-কোয়েরিতে এর কোনও রেফারেন্স fooনা থাকলে ডিবি-সার্ভার স্থির সামগ্রী হিসাবে অনুকূলিত হতে পারে এবং কেবল একবারেই মূল্যায়ন করতে পারে।

কোথায়-বিবৃতিতে সাব-কোয়েরি

SELECT moo FROM foo WHERE bar = (SELECT roger FROM wilco WHERE moo = me)

আপনি যদি ভাগ্যবান হন তবে ডিবি অভ্যন্তরীণভাবে এটিকে অনুকূলিত করে JOIN। যদি তা না হয় তবে আপনার কোয়েরিটি বিশাল ডেটাসেটগুলিতে খুব ধীরে ধীরে হয়ে যাবে কারণ এটি প্রতিটি সারিটির জন্য সাব-কোয়েরি কার্যকর করবে foo, কেবলমাত্র নির্বাচনের ধরণের মতো ফলাফল নয়।

যোগদান-বিবৃতিতে সাব-কোয়েরি

SELECT moo, bar 
  FROM foo 
    LEFT JOIN (
      SELECT MIN(bar), me FROM wilco GROUP BY me
    ) ON moo = me

এটা মজার. আমরা JOINএকটি সাব-কোয়েরির সাথে একত্রিত করি । এবং এখানে আমরা সাব-কোয়েরিগুলির আসল শক্তি পাই। wilcoকয়েক মিলিয়ন সারি রয়েছে এমন একটি ডেটাসেট কল্পনা করুন তবে কয়েকটি আলাদা me। বিশাল টেবিলের বিপরীতে যোগদানের পরিবর্তে, আমাদের বিপরীতে যোগদানের জন্য এখন একটি ছোট অস্থায়ী টেবিল রয়েছে। এটি ডেটাবেস আকারের উপর নির্ভর করে অনেক দ্রুত ক্যোয়ারী তৈরি করতে পারে। আপনার সাথে একই প্রভাব থাকতে পারে CREATE TEMPORARY TABLE ...এবং INSERT INTO ... SELECT ...এটি খুব জটিল প্রশ্নগুলিতে আরও ভাল পঠনযোগ্যতা সরবরাহ করতে পারে (তবে পুনরাবৃত্তযোগ্য পাঠ্য বিচ্ছিন্নতার স্তরে ডেটাসেটগুলি লক করতে পারে)।

নেস্টেড সাব-কোয়েরি

SELECT moo, bar
  FROM (
    SELECT moo, CONCAT(roger, wilco) AS bar
      FROM foo
      GROUP BY moo
      HAVING bar LIKE 'SpaceQ%'
  ) AS temp_foo
  ORDER BY bar

আপনি একাধিক স্তরে সাব-কোয়েরি বাসাতে পারেন। যদি আপনাকে ফলাফলগুলি গোছাতে বা বাছাই করতে হয় তবে এটি বিশাল ডেটাसेटগুলিতে সহায়তা করতে পারে। সাধারণত ডিবি-সার্ভার এটির জন্য একটি অস্থায়ী টেবিল তৈরি করে, তবে কখনও কখনও আপনার পুরো টেবিলে বাছাই করার প্রয়োজন হয় না, কেবল ফলাফলসেটে। এটি টেবিলের আকারের উপর নির্ভর করে আরও ভাল পারফরম্যান্স সরবরাহ করতে পারে।

উপসংহার

উপ-প্রশ্নগুলি কোনওটির জন্য কোনও প্রতিস্থাপন JOINনয় এবং আপনার এগুলি (যদিও সম্ভব) এটি ব্যবহার করা উচিত নয়। আমার বিনীত মতে, সাব-কোয়েরিটির সঠিক ব্যবহার হ'ল একটি দ্রুত প্রতিস্থাপন হিসাবে ব্যবহার CREATE TEMPORARY TABLE ...। একটি ভাল সাব-ক্যোয়ারী একটি উপাত্তকে এমনভাবে হ্রাস করে যাতে আপনি এ এর ONবিবৃতিতে সম্পূর্ণ করতে পারবেন না JOIN। যদি একটি সাব-কোয়েরিতে একটি কীওয়ার্ড থাকে GROUP BYবা DISTINCTএটি পছন্দমতো নির্বাচিত ক্ষেত্রগুলিতে বা যেখানে বিবৃতিতে থাকে না, তবে এটি কার্য সম্পাদনকে অনেক উন্নত করতে পারে।


3
এর জন্য Sub-queries in the Join-statement: (১) সাব-কোয়েরি থেকে উত্পন্ন টেবিল তৈরি করা খুব দীর্ঘ সময় নিতে পারে। (2) ফলাফল প্রাপ্ত টেবিল সূচী হয় না। এই দু'জনেই এসকিউএল উল্লেখযোগ্যভাবে কমিয়ে দিতে পারে।
jxc

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

আইএমও: (১) এই জাতীয় অস্থায়ী টেবিল (উত্পন্ন টেবিল) বাস্তবায়িত হয় না, সুতরাং আপনি এসকিউএল চালানোর সময় অস্থায়ী টেবিলটি পুনরায় তৈরি করতে হবে, এটি খুব ব্যয়বহুল এবং সত্যিকারের বোতল-নেক হতে পারে (অর্থাত্ লক্ষ লক্ষ লোকের দ্বারা একটি দল চালাচ্ছেন) রেকর্ডগুলির) (2) এমনকি যদি আপনি 10কোনও টেক্স টেবিলের আকার রেকর্ডে হ্রাস করতে পারেন , যেহেতু কোনও সূচক নেই, তারপরেও অন্য টেবিলগুলিতে যোগদান করার সময় টেম্প টেবিলের চেয়ে 9 গুণ বেশি ডেটা রেকর্ডের কোয়েরি করা সম্ভব। বিটিডাব্লু এর আগে আমার ডিবি (মাইএসকিউএল) এর সাথে আমার এই সমস্যাটি ছিল, আমার ক্ষেত্রে সাব-কোয়েরি ব্যবহার SELECT listকরা আরও দ্রুততর হতে পারে।
jxc

@jxc আমি সন্দেহ করি না যে এখানে প্রচুর উদাহরণ রয়েছে, যেখানে সাবকিউরিটি ব্যবহার করা কম অনুকূল। ভাল অনুশীলন হিসাবে আপনার EXPLAINঅনুকূলকরণের আগে একটি প্রশ্নের উপর ব্যবহার করা উচিত । পুরানোগুলির সাথে set profiling=1আপনি সহজেই দেখতে পেলেন, কোনও অস্থায়ী টেবিলটি যদি কোনও বাধা হয়ে থাকে। এমনকি একটি সূচককে প্রক্রিয়াকরণের সময়ও প্রয়োজন, বি-ট্রিগুলি রেকর্ডগুলির জন্য অনুসন্ধানকে অনুকূলিত করে, তবে একটি 10 ​​রেকর্ড সারণী কয়েক মিলিয়ন রেকর্ডের জন্য সূচকের চেয়ে অনেক দ্রুত হতে পারে। তবে ক্ষেত্রের আকার এবং প্রকারের মতো একাধিক কারণের উপর এটি নির্ভর করে।
ট্রেন্ডফিশার

1
আমি সত্যিই আপনার ব্যাখ্যা উপভোগ করেছি। ধন্যবাদ.
2-2 এ অপ্রত্যাশিত গুড

43

প্রথমত, দু'জনের তুলনা করার জন্য আপনার সাব-কোয়েরিতে প্রশ্নের আলাদা করতে হবে:

  1. সাবকিউরিয়াসগুলির একটি শ্রেণিতে সর্বদা যোগদানের সাথে সমান সমতুল্য ক্যোয়ারী লেখা থাকে
  2. যোগসূতী ব্যবহার করে পুনরায় লেখা যায় না এমন এক শ্রেণির সাবকোয়ারি

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

এই দিনগুলি এমনকি মাইএসকিএল এটি করে।

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

উপসংহারটি হ'ল যোগদান এবং সাবকিউরি ভেরিয়েন্ট উভয়ের জন্য আপনার প্রশ্নের পরীক্ষা করা উচিত যদি আপনি নিশ্চিত হন যে কোনটি আরও ভালভাবে সম্পাদন করবে।

দ্বিতীয় শ্রেণীর জন্য এই তুলনাটি কোনও অর্থবোধ করে না কারণ এই প্রশ্নগুলি যোগদান করে নতুন করে লেখা যায় না এবং এই ক্ষেত্রে সাবকিউরিগুলি প্রয়োজনীয় কাজগুলি করার প্রাকৃতিক উপায় এবং আপনার তাদের সাথে বৈষম্যমূলক আচরণ করা উচিত নয়।


1
আপনি কি সাব-কোয়েরি ব্যবহার করে লিখিত একটি ক্যোয়ারির উদাহরণ প্রদান করতে পারেন যা যোগদানের সাথে রূপান্তরিত হতে পারে না (দ্বিতীয় শ্রেণি, যেমন আপনি এটি ডাকছেন)?
জহরা

24

আমি মনে করি উদ্ধৃত উত্তরগুলিতে যা জোর দেওয়া হয়েছে তা হ'ল নকল এবং সমস্যাযুক্ত ফলাফল যা নির্দিষ্ট (ব্যবহার) ক্ষেত্রে উত্থাপিত হতে পারে the

(যদিও মার্সেলো ক্যান্টোস এটি উল্লেখ করে)

আমি এসকিউএল-এর স্ট্যানফোর্ডের লাগুনিটা কোর্সগুলির উদাহরণটি উদ্ধৃত করব।

শিক্ষার্থীদের টেবিল

+------+--------+------+--------+
| sID  | sName  | GPA  | sizeHS |
+------+--------+------+--------+
|  123 | Amy    |  3.9 |   1000 |
|  234 | Bob    |  3.6 |   1500 |
|  345 | Craig  |  3.5 |    500 |
|  456 | Doris  |  3.9 |   1000 |
|  567 | Edward |  2.9 |   2000 |
|  678 | Fay    |  3.8 |    200 |
|  789 | Gary   |  3.4 |    800 |
|  987 | Helen  |  3.7 |    800 |
|  876 | Irene  |  3.9 |    400 |
|  765 | Jay    |  2.9 |   1500 |
|  654 | Amy    |  3.9 |   1000 |
|  543 | Craig  |  3.4 |   2000 |
+------+--------+------+--------+

টেবিল প্রয়োগ করুন

(নির্দিষ্ট বিশ্ববিদ্যালয় এবং মেজরগুলিতে করা অ্যাপ্লিকেশন)

+------+----------+----------------+----------+
| sID  | cName    | major          | decision |
+------+----------+----------------+----------+
|  123 | Stanford | CS             | Y        |
|  123 | Stanford | EE             | N        |
|  123 | Berkeley | CS             | Y        |
|  123 | Cornell  | EE             | Y        |
|  234 | Berkeley | biology        | N        |
|  345 | MIT      | bioengineering | Y        |
|  345 | Cornell  | bioengineering | N        |
|  345 | Cornell  | CS             | Y        |
|  345 | Cornell  | EE             | N        |
|  678 | Stanford | history        | Y        |
|  987 | Stanford | CS             | Y        |
|  987 | Berkeley | CS             | Y        |
|  876 | Stanford | CS             | N        |
|  876 | MIT      | biology        | Y        |
|  876 | MIT      | marine biology | N        |
|  765 | Stanford | history        | Y        |
|  765 | Cornell  | history        | N        |
|  765 | Cornell  | psychology     | Y        |
|  543 | MIT      | CS             | N        |
+------+----------+----------------+----------+

আসুন CSমেজর (বিশ্ববিদ্যালয় নির্বিশেষে) প্রয়োগ করা শিক্ষার্থীদের জন্য জিপিএ স্কোরগুলি সন্ধান করার চেষ্টা করি

একটি subquery ব্যবহার:

select GPA from Student where sID in (select sID from Apply where major = 'CS');

+------+
| GPA  |
+------+
|  3.9 |
|  3.5 |
|  3.7 |
|  3.9 |
|  3.4 |
+------+

এই রেজাল্টটির জন্য গড় মূল্য:

select avg(GPA) from Student where sID in (select sID from Apply where major = 'CS');

+--------------------+
| avg(GPA)           |
+--------------------+
| 3.6800000000000006 |
+--------------------+

একটি যোগদান যোগদান:

select GPA from Student, Apply where Student.sID = Apply.sID and Apply.major = 'CS';

+------+
| GPA  |
+------+
|  3.9 |
|  3.9 |
|  3.5 |
|  3.7 |
|  3.7 |
|  3.9 |
|  3.4 |
+------+

এই ফলাফলের জন্য গড় মান:

select avg(GPA) from Student, Apply where Student.sID = Apply.sID and Apply.major = 'CS';

+-------------------+
| avg(GPA)          |
+-------------------+
| 3.714285714285714 |
+-------------------+

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

দেখে মনে হচ্ছে যে কোনও ক্ষেত্রে কোনও উপ-ক্যোয়ারী কোনও কার্য সম্পাদনের সমস্যা ছাড়াও নিরাপদতম উপায়।


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

22

এসকিউএল সার্ভারের জন্য এমএসডিএন ডকুমেন্টেশন বলেছে

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

সুতরাং যদি আপনার মতো কিছু দরকার হয়

select * from t1 where exists select * from t2 where t2.parent=t1.id

পরিবর্তে যোগদান ব্যবহার করার চেষ্টা করুন। অন্যান্য ক্ষেত্রে, এটি কোনও পার্থক্য করে না।

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

কোডের মধ্যে বিশৃঙ্খলা একটি বড় সমস্যা এবং যুগ যুগ ধরে শিল্প এড়াতে কাজ করে চলেছে।


9
কিছু আরডিবিএমএস (উদাঃ ওরাকল) এর কার্যকারণ অনুসারে ফাংশনগুলির সাথে সাবকিউরিজগুলি প্রতিস্থাপন করা খুব খারাপ ধারণা so সুতরাং আমি ঠিক তার বিপরীতে সুপারিশ করব - যেখানে সম্ভব সেখানে ফাংশনগুলির পরিবর্তে সাবকিউরিগুলি / যোগদান করুন।
ফ্রাঙ্ক স্মিট

3
@ ফ্র্যাঙ্কশ্মিট দয়া করে আপনার যুক্তিকে রেফারেন্স সহ সমর্থন করুন।
Uğur Güşmüşhan

2
এমন কিছু ঘটনাও রয়েছে যেখানে অস্তিত্বের জন্য যাচাই করে নেওয়া সত্ত্বেও আপনার যোগদানের পরিবর্তে সাব কোয়েরি ব্যবহার করা উচিত: যদি আপনি পরীক্ষা করে থাকেন NOT EXISTS। একটি NOT EXISTSএকটি ওভার জয়ী LEFT OUTER JOIN বিভিন্ন কারণের জন্য: preformance, ব্যর্থ নিরাপত্তা এবং পাঠযোগ্যতা (nulable কলামের ক্ষেত্রে)। sqlperformance.com/2012/12/t-sql-queries/left-anti-semi-join
টিম শেমলেটার

16

পুরানো মাম্বো সিএমএস থেকে একটি খুব বড় ডাটাবেস চালান:

SELECT id, alias
FROM
  mos_categories
WHERE
  id IN (
    SELECT
      DISTINCT catid
    FROM mos_content
  );

0 সেকেন্ড

SELECT
  DISTINCT mos_content.catid,
  mos_categories.alias
FROM
  mos_content, mos_categories
WHERE
  mos_content.catid = mos_categories.id;

Seconds 3 সেকেন্ড

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

এবং...

SELECT
  DISTINCT mos_categories.id,
  mos_categories.alias
FROM
  mos_content, mos_categories
WHERE
  mos_content.catid = mos_categories.id;

0 সেকেন্ড

আবার একই ফলাফল, একই সংখ্যক সারি পরীক্ষা করা হয়েছে। আমার ধারণা হ'ল DISTINCT মোস_কন্টিটিরিয়ালিটি.আইডিএসএনসিটি মোস_ক্যাটরিজ.আইডি থেকে তুলনায় অনেক বেশি সময় নেয়।


1
আপনি শেষ লাইনে আপনি কী উল্লেখ করতে চাইছেন সে সম্পর্কে আমি আরও জানতে চাই "" আমার ধারণা হ'ল DISTINCT মোস_কন্টিটি.এটিড DISTINCT মোস_ক্যাটরিজ.আইডির চেয়ে অনেক বেশি সময় নেয় "" । আপনি কি বলছেন যে কোনও আইডি কেবল নামকরণ করা উচিত idএবং এর মতো কিছু নামকরণ করা উচিত নয় catid? আমার ডিবি অ্যাক্সেসগুলি অপ্টিমাইজ করার চেষ্টা করছে এবং আপনার শিক্ষাগুলি সাহায্য করতে পারে।
bool.dev

1
সেক্ষেত্রে এসকিউএল ইন ব্যবহার করা একটি খারাপ অভ্যাস এবং এটি কোনও প্রমাণ দেয় না।
Uğur Güşmüşhan

15

আমার দুটি মত পর্যবেক্ষণ অনুসারে, যদি কোনও টেবিলের কম পরিমাণে 100,000 রেকর্ড থাকে তবে জোড় দ্রুত কাজ করবে।

তবে যে ক্ষেত্রে কোনও টেবিলের ১০০,০০০ রেকর্ডেরও বেশি রেকর্ড রয়েছে তারপরে একটি সাবকিউরিটি সেরা ফলাফল।

আমার কাছে একটি টেবিল রয়েছে যার উপরে 500,000 রেকর্ড রয়েছে যা আমি কোয়েরির নীচে তৈরি করেছি এবং এর ফলাফলের সময়টি এর মতো

SELECT * 
FROM crv.workorder_details wd 
inner join  crv.workorder wr on wr.workorder_id = wd.workorder_id;

ফলাফল: 13.3 সেকেন্ড

select * 
from crv.workorder_details 
where workorder_id in (select workorder_id from crv.workorder)

ফলাফল: 1.65 সেকেন্ড


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

1
আপনার যোগ দিয়ে বেঁধে রাখুন যথেষ্ট দ্রুত কাজ করছেন না, আপনি হয়ত একটি সূচক মিস করছেন। অনুসন্ধান বিশ্লেষক প্রকৃত পারফরম্যান্সের তুলনায় বেশ সহায়ক হতে পারে।
ডিজিটাল.আআরন

আমি অজয় ​​গাজেরার সাথে একমত, আমি এটি নিজের জন্য দেখেছি।
ব্যবহারকারী 1735921

14
দুটি ফলাফলের পারফরম্যান্সের সাথে তুলনা করতে কীভাবে এটি বোধগম্য হয় যা বিভিন্ন ফলাফল দেয়?
পল স্পিগেল

হ্যাঁ এগুলি আলাদা আলাদা প্রশ্ন তবে একই ফলাফল ফিরে আসছে
রাজা নিও

12

সাবকিউরিগুলি সাধারণত একটি একক সারিটিকে পারমাণবিক মান হিসাবে ফিরিয়ে আনতে ব্যবহৃত হয়, যদিও এগুলি আইএন কীওয়ার্ডের সাথে একাধিক সারিগুলির সাথে মানগুলির তুলনা করতে ব্যবহৃত হতে পারে। লক্ষ্য তালিকা, WHERE ধারা এবং অন্যান্য সহ এসকিউএল স্টেটমেন্টের প্রায় কোনও অর্থবোধক বিন্দুতে তাদের অনুমতি দেওয়া হয়। একটি সাধারণ সাব-কোয়েরি অনুসন্ধান শর্ত হিসাবে ব্যবহার করা যেতে পারে। উদাহরণস্বরূপ, এক জোড়া টেবিলের মধ্যে:

   SELECT title FROM books WHERE author_id = (SELECT id FROM authors WHERE last_name = 'Bar' AND first_name = 'Foo');

নোট করুন যে সাব-কোয়েরির ফলাফলগুলিতে একটি সাধারণ মান অপারেটর ব্যবহারের প্রয়োজন কেবলমাত্র একটি ক্ষেত্রকেই ফেরত দিতে হবে। আপনি যদি অন্য মানগুলির সেটের মধ্যে একক মানের অস্তিত্বের জন্য যাচাই করতে আগ্রহী হন তবে IN:

   SELECT title FROM books WHERE author_id IN (SELECT id FROM authors WHERE last_name ~ '^[A-E]');

এটি স্পষ্টতই একটি লেফট-জয়েন্ট বলতে আলাদা যেখানে আপনি কেবল সারণি A এবং B থেকে স্টাফগুলিতে যোগদান করতে চান এমনকি জয়েন-শর্তটি সারণী বি ইত্যাদিতে কোনও মিল খুঁজে পাওয়া যায় না etc.

আপনি যদি গতি সম্পর্কে কেবল চিন্তিত হন তবে আপনাকে আপনার ডাটাবেসটি পরীক্ষা করে দেখতে হবে এবং একটি ভাল ক্যোয়ারী লিখতে হবে এবং পারফরম্যান্সে কোনও উল্লেখযোগ্য পার্থক্য রয়েছে কিনা তা দেখতে হবে।


11

মাইএসকিউএল সংস্করণ: 5.5.28-0ubuntu0.12.04.2-লগ

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

3 টি উপ-প্রশ্নের সাথে এখানে আমার জিজ্ঞাসা:

EXPLAIN SELECT vrl.list_id,vrl.ontology_id,vrl.position,l.name AS list_name, vrlih.position AS previous_position, vrl.moved_date 
FROM `vote-ranked-listory` vrl 
INNER JOIN lists l ON l.list_id = vrl.list_id 
INNER JOIN `vote-ranked-list-item-history` vrlih ON vrl.list_id = vrlih.list_id AND vrl.ontology_id=vrlih.ontology_id AND vrlih.type='PREVIOUS_POSITION' 
INNER JOIN list_burial_state lbs ON lbs.list_id = vrl.list_id AND lbs.burial_score < 0.5 
WHERE vrl.position <= 15 AND l.status='ACTIVE' AND l.is_public=1 AND vrl.ontology_id < 1000000000 
 AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=43) IS NULL 
 AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=55) IS NULL 
 AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=246403) IS NOT NULL 
ORDER BY vrl.moved_date DESC LIMIT 200;

ব্যাখ্যা শো:

+----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
| id | select_type        | table    | type   | possible_keys                                       | key          | key_len | ref                                             | rows | Extra                    |
+----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+
|  1 | PRIMARY            | vrl      | index  | PRIMARY                                             | moved_date   | 8       | NULL                                            |  200 | Using where              |
|  1 | PRIMARY            | l        | eq_ref | PRIMARY,status,ispublic,idx_lookup,is_public_status | PRIMARY      | 4       | ranker.vrl.list_id                              |    1 | Using where              |
|  1 | PRIMARY            | vrlih    | eq_ref | PRIMARY                                             | PRIMARY      | 9       | ranker.vrl.list_id,ranker.vrl.ontology_id,const |    1 | Using where              |
|  1 | PRIMARY            | lbs      | eq_ref | PRIMARY,idx_list_burial_state,burial_score          | PRIMARY      | 4       | ranker.vrl.list_id                              |    1 | Using where              |
|  4 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
|  3 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
|  2 | DEPENDENT SUBQUERY | list_tag | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.l.list_id,const                          |    1 | Using where; Using index |
+----+--------------------+----------+--------+-----------------------------------------------------+--------------+---------+-------------------------------------------------+------+--------------------------+

JOINs এর সাথে একই প্রশ্নটি হ'ল:

EXPLAIN SELECT vrl.list_id,vrl.ontology_id,vrl.position,l.name AS list_name, vrlih.position AS previous_position, vrl.moved_date 
FROM `vote-ranked-listory` vrl 
INNER JOIN lists l ON l.list_id = vrl.list_id 
INNER JOIN `vote-ranked-list-item-history` vrlih ON vrl.list_id = vrlih.list_id AND vrl.ontology_id=vrlih.ontology_id AND vrlih.type='PREVIOUS_POSITION' 
INNER JOIN list_burial_state lbs ON lbs.list_id = vrl.list_id AND lbs.burial_score < 0.5 
LEFT JOIN list_tag lt1 ON lt1.list_id = vrl.list_id AND lt1.tag_id = 43 
LEFT JOIN list_tag lt2 ON lt2.list_id = vrl.list_id AND lt2.tag_id = 55 
INNER JOIN list_tag lt3 ON lt3.list_id = vrl.list_id AND lt3.tag_id = 246403 
WHERE vrl.position <= 15 AND l.status='ACTIVE' AND l.is_public=1 AND vrl.ontology_id < 1000000000 
AND lt1.list_id IS NULL AND lt2.tag_id IS NULL 
ORDER BY vrl.moved_date DESC LIMIT 200;

এবং আউটপুটটি হ'ল:

+----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
| id | select_type | table | type   | possible_keys                                       | key          | key_len | ref                                         | rows | Extra                                        |
+----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+
|  1 | SIMPLE      | lt3   | ref    | list_tag_key,list_id,tag_id                         | tag_id       | 5       | const                                       | 2386 | Using where; Using temporary; Using filesort |
|  1 | SIMPLE      | l     | eq_ref | PRIMARY,status,ispublic,idx_lookup,is_public_status | PRIMARY      | 4       | ranker.lt3.list_id                          |    1 | Using where                                  |
|  1 | SIMPLE      | vrlih | ref    | PRIMARY                                             | PRIMARY      | 4       | ranker.lt3.list_id                          |  103 | Using where                                  |
|  1 | SIMPLE      | vrl   | ref    | PRIMARY                                             | PRIMARY      | 8       | ranker.lt3.list_id,ranker.vrlih.ontology_id |   65 | Using where                                  |
|  1 | SIMPLE      | lt1   | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.lt3.list_id,const                    |    1 | Using where; Using index; Not exists         |
|  1 | SIMPLE      | lbs   | eq_ref | PRIMARY,idx_list_burial_state,burial_score          | PRIMARY      | 4       | ranker.vrl.list_id                          |    1 | Using where                                  |
|  1 | SIMPLE      | lt2   | ref    | list_tag_key,list_id,tag_id                         | list_tag_key | 9       | ranker.lt3.list_id,const                    |    1 | Using where; Using index                     |
+----+-------------+-------+--------+-----------------------------------------------------+--------------+---------+---------------------------------------------+------+----------------------------------------------+

rowsকলামের একটি তুলনা পার্থক্যটি জানায় এবং JOINs সহ কোয়েরিটি ব্যবহার করছেUsing temporary; Using filesort

অবশ্যই যখন আমি উভয় প্রশ্নের চালনা করি, প্রথমটি 0.02 সেকেন্ডে করা হয়, দ্বিতীয়টি 1 মিনিটের পরেও সম্পূর্ণ হয় না, সুতরাং এই প্রশ্নগুলি সঠিকভাবে ব্যাখ্যা করলেন।

যদি আমার list_tagটেবিলে অভ্যন্তরীণ যোগদান না হয় অর্থাৎ আমি সরিয়ে দিই

AND (SELECT list_id FROM list_tag WHERE list_id=l.list_id AND tag_id=246403) IS NOT NULL  

প্রথম জিজ্ঞাসা থেকে এবং অনুরূপ:

INNER JOIN list_tag lt3 ON lt3.list_id = vrl.list_id AND lt3.tag_id = 246403

দ্বিতীয় ক্যোয়ারী থেকে, তারপরে ব্যাখ্যা করুন উভয় প্রশ্নের জন্য একই সংখ্যক সারি ফেরত দেয় এবং এই উভয় কোয়েরি সমান দ্রুত চলে।


আমারও একই অবস্থা, তবে আপনার চেয়ে আরও বেশি যোগদানের সাথে একবার ব্যাখ্যা করার চেষ্টা করব
pahnin

ওরাকল বা পোস্টগ্রিএসকিউএল-তে আমি চেষ্টা করে দেখেছি: এবং অস্তিত্ব নেই (তালিকা থেকে 1 টি তালিকা নির্বাচন করুন_লিপি_লিস্ট_আইডি এবং ট্যাগ_আইডে (43, 55, 246403))
ডেভিড

11

সাবকিউরিতে একটি ফ্লাইতে একত্রিতকরণ কার্যগুলি গণনা করার ক্ষমতা রয়েছে। উদাহরণস্বরূপ বইটির সর্বনিম্ন দাম সন্ধান করুন এবং এই দামের সাথে বিক্রি হওয়া সমস্ত বই পান। 1) সাবকিউরিস ব্যবহার:

SELECT titles, price
FROM Books, Orders
WHERE price = 
(SELECT MIN(price)
 FROM Orders) AND (Books.ID=Orders.ID);

2) JOINs ব্যবহার করে

SELECT MIN(price)
     FROM Orders;
-----------------
2.99

SELECT titles, price
FROM Books b
INNER JOIN  Orders o
ON b.ID = o.ID
WHERE o.price = 2.99;

আরেকটি মামলা: একাধিক GROUP BYবিভিন্ন টেবিল সঙ্গে S: stackoverflow.com/questions/11415284/... Subqueries কঠোরভাবে আরও সাধারণ বলে মনে হচ্ছে। মাইএসকিউএল ম্যানটিও দেখুন: dev.mysql.com/doc/refman/5.7/en/optimizing-subqueries.html | dev.mysql.com/doc/refman/5.7/en/rewriting-subqueries.html
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功

6
-1 আপনি বিভাজন ব্যবহার করছেন এবং উভয় উদাহরণে যোগ দেওয়ার কারণে এটি বিভ্রান্তিকর। সর্বনিম্ন অর্ডার দাম নির্ধারণের জন্য আপনি সাবকিরিটিকে দ্বিতীয় কোয়েরিতে টানলেন যেহেতু ডাটাবেস ঠিক একই কাজ করবে will এছাড়াও, আপনি একটি subquery ব্যবহার করে যোগদান পুনরায় লিখছেন না; উভয় প্রশ্নের একটি যোগদান ব্যবহার করে। আপনি হয় সঠিক যে subqueries সমষ্টিগত ফাংশন দিই, কিন্তু এই উদাহরণে আসলে প্রকট করে না।
ডেভিড হার্কনেস

আমি ডেভিডের সাথে একমত, এবং আপনি সর্বনিম্ন দাম পাওয়ার জন্য গ্রুপ ব্যবহার করতে পারেন।
ব্যবহারকারী 1735921

9
  • একটি সাধারণ নিয়ম হল বেশিরভাগ ক্ষেত্রে (99%) দ্রুত যোগ দেয়
  • যত বেশি ডেটা টেবিল রয়েছে, সাবকুরিগুলি ধীরে ধীরে।
  • যত কম ডাটা টেবিল রয়েছে, সাবক্রাইরিগুলিতে যোগদানের সাথে সমতুল্য গতি রয়েছে ।
  • Subqueries , সহজতর বুঝতে সহজ, অথবা পড়ার জন্য সহজ হয়।
  • বেশিরভাগ ওয়েব এবং অ্যাপ্লিকেশন ফ্রেমওয়ার্ক এবং তাদের "ওআরএম" গুলি এবং "অ্যাক্টিভ রেকর্ড" এর উপকোয়ারীর সাথে কোয়েরি উত্পন্ন করে , কারণ সাবকিউয়ের সাথে দায়িত্ব বিভক্ত করা, কোড বজায় রাখা ইত্যাদি সহজ are
  • ছোট ওয়েবসাইট বা অ্যাপ্লিকেশনগুলির জন্য সাবকিউরিগুলি ঠিক আছে তবে বৃহত্তর ওয়েব সাইট এবং অ্যাপ্লিকেশনগুলির জন্য আপনাকে প্রায়শই উত্পন্ন উত্সগুলি পুনরায় লিখতে হবে ক্যোয়ারিতে যোগ দিতে , বিশেষত যদি কোয়েরিতে কোয়েরিতে অনেকগুলি সাবকিউরি ব্যবহার করা হয় ।

তারপর অনেকে তো বলে "কিছু RDBMS একটি পুনর্লিখন করতে subquery একটি থেকে যোগদানের বা যোগদানের একটি থেকে subquery যখন এটি মনে এক দ্রুত অন্য চেয়ে আছে।", কিন্তু এই বিবৃতি সহজ ক্ষেত্রে, নিশ্চয় না জটিল প্রশ্নের সঙ্গে প্রযোজ্য subqueries যা আসলে একটি কারণ কর্মক্ষমতা সমস্যা।


> তবে এই বিবৃতিটি সাধারণ ক্ষেত্রে প্রযোজ্য আমি বুঝতে পেরেছিলাম যে এটি হয় একটি সহজ কেস যা আরডিবিএমএস দ্বারা "যোগ" এ পুনরায় লেখা যেতে পারে, বা এটি এমন জটিল কেস যা এখানে সাবকিউরিগুলি উপযুক্ত। :-) ওআরএমগুলিতে দুর্দান্ত পয়েন্ট। আমি মনে করি এটির সবচেয়ে বেশি প্রভাব রয়েছে has
পাইলট

4

পার্থক্যটি কেবল তখনই দেখা যায় যখন দ্বিতীয় যোগদানের টেবিলটিতে প্রাথমিক সারণির চেয়ে উল্লেখযোগ্য পরিমাণে বেশি ডেটা থাকবে। আমি নীচের মত একটি অভিজ্ঞতা ছিল ...

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

তবে মাঝামাঝি সময়ে যোগদানের প্রশ্নগুলি অন্যান্য সারণীর সাথে কাজ করছে যেখানে প্রাথমিক সারণির চেয়ে কম প্রবেশিকা রয়েছে।

সুতরাং আমি মনে করি যোগদান এবং উপ-ক্যোয়ারী বিবৃতিগুলি ঠিকঠাকভাবে কাজ করছে এবং এটি ডেটা এবং পরিস্থিতির উপর নির্ভর করে।


2

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


1

আমি কেবল একই সমস্যাটি নিয়ে ভাবছি তবে আমি এফআরএম অংশে সাবকিউরিটি ব্যবহার করছি। আমার বড় টেবিলগুলি থেকে সংযোগ এবং ক্যোয়ারী দরকার, "দাস" সারণীতে ২৮ মিলিয়ন রেকর্ড রয়েছে তবে ফলাফলটি কেবলমাত্র 128 এত ছোট ফলাফলের বড় ডেটা! আমি এটিতে MAX () ফাংশনটি ব্যবহার করছি।

প্রথমে আমি বাম জয়েন্ট ব্যবহার করছি কারণ আমি মনে করি যে এটিই সঠিক উপায়, মাইএসকিএল ইত্যাদি অনুকূলিতকরণ করতে পারে Second দ্বিতীয়বার কেবল পরীক্ষার জন্য, আমি আবার জয়েনের বিরুদ্ধে সাব-সিলেক্ট করতে লিখি w

বাম যোগদানের সময়: 1.12 এস সাব-নির্বাচন রানটাইম: 0.06 এস

যোগ চেয়ে 18 গুণ দ্রুত সাবলেট! স্রেফ চোকিটো এড। সাবলেটটি ভয়ঙ্কর দেখায় তবে ফলাফল ...


-1

আপনি যদি যোগ করুন ব্যবহার করে আপনার ক্যোয়ারীটি দ্রুত করতে চান:

"অভ্যন্তরীণ যোগদান / যোগদান" এর জন্য, যেখানে শর্ত পরিবর্তে এটি "চালু" অবস্থায় ব্যবহার করবেন না। উদাহরণ:

     select id,name from table1 a  
   join table2 b on a.name=b.name
   where id='123'

 Try,

    select id,name from table1 a  
   join table2 b on a.name=b.name and a.id='123'

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


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