দ্রুত কি, মাইএসকিউএল থেকে নির্বাচন বা গ্রুপ নির্বাচন?


273

আমার যদি টেবিল থাকে

CREATE TABLE users (
  id int(10) unsigned NOT NULL auto_increment,
  name varchar(255) NOT NULL,
  profession varchar(255) NOT NULL,
  employer varchar(255) NOT NULL,
  PRIMARY KEY  (id)
)

এবং আমি professionক্ষেত্রের সমস্ত অনন্য মান পেতে চাই , কী দ্রুত হবে (বা প্রস্তাবিত):

SELECT DISTINCT u.profession FROM users u

অথবা

SELECT u.profession FROM users u GROUP BY u.profession

?


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

ভিন্ন উত্তর সহ আরও একটি সদৃশ আছে।
মাইএসকিউএল

আপনি যদি আপনার ক্যোয়ারী চালিয়ে DISTINCT এবং GROUP এর মধ্যে সময়ের পার্থক্যটি পরিমাপ করতে চান তবে দয়া করে এখানে দেখুন ।
কলুনার

উত্তর:


258

এগুলি মূলত একে অপরের সমতুল্য (বাস্তবে DISTINCTহুডের অধীনে কিছু ডাটাবেস বাস্তবায়িত হয়)।

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

সন্দেহ হলে পরীক্ষা!


76
DISTINCT কেবল তখনই ত্বরান্বিত হবে যখন আপনার একটি সূচক না করায় (যেমন এটি সাজান না)। আপনার যখন কোনও সূচক থাকে এবং এটি ব্যবহৃত হয়, তখন এগুলি প্রতিশব্দ।
কাসনসুই

10
সংজ্ঞা DISTINCTএবং এর মধ্যে GROUP BYপৃথক হয় DISTINCTআউটপুট বাছাই করতে হবে না, এবং GROUP BYডিফল্টরূপে। যাইহোক, মাইএসকিউএলে এমনকি স্কয়ারকোগের ব্যাখ্যা অনুসারে অপ্টিমাইজারের জন্য অতিরিক্ত ইঙ্গিতগুলির কারণে একটি DISTINCT+ এখনও আরও দ্রুত ORDER BYহতে পারে । GROUP BY
rustyx

1
DISTINCT বড় পরিমাণের ডেটা সহ অনেক দ্রুত।
পঙ্কজ ওয়াঞ্জারি

7
আমি এটি পরীক্ষা করেছি এবং দেখতে পেয়েছি যে একটি সূচিযুক্ত কলামে, মাইএসকিএল, গোষ্ঠীটি মোটামুটি জটিল প্রশ্নের সাথে পৃথকের চেয়ে প্রায় 6x ধীর ছিল। এটি কেবল ডেটাপয়েন্ট হিসাবে যুক্ত করুন। প্রায় 100k সারি। সুতরাং এটি পরীক্ষা করুন এবং নিজেরাই দেখুন।
Lizardx


100

আপনার যদি সূচক থাকে তবে professionএই দুটি সমার্থক শব্দ।

যদি তা না হয়, তাহলে ব্যবহার DISTINCT

GROUP BYমধ্যে MySQLপ্রকারের ফলাফল নেই। আপনি এমনকি করতে পারেন:

SELECT u.profession FROM users u GROUP BY u.profession DESC

এবং আপনার পেশাগুলি DESCক্রম অনুসারে সাজান ।

DISTINCTএকটি অস্থায়ী টেবিল তৈরি করে এবং এটি নকল সংরক্ষণের জন্য ব্যবহার করে। GROUP BYএকই কাজ করে তবে স্বতন্ত্র ফলাফলগুলি পরে sortes করে।

সুতরাং

SELECT DISTINCT u.profession FROM users u

দ্রুততর, যদি আপনার কোনও সূচক না থাকে profession


6
আপনি বাছাই এড়াতে যোগ ORDER BY NULLকরতে GROUP BYপারেন।
এরিয়েল

নাল দ্বারা গ্রুপিংয়ের পরেও ধীর
থানহ ট্রুং

@ থানহত্রং: কিসের চেয়ে ধীর?
কাসনসুই

@ কোসনোই গ্রুপ্বি দ্বারা বাছাই এড়াতে স্বতন্ত্রের চেয়ে ধীরে ধীরে
থানহ ট্রুং

দ্রষ্টব্য: গ্রুপ দ্বারা অর্ডার কোয়ালিফায়ারদের মাইএসকিউএল ৮
ম্যাথু লেনেজ ২

18

উপরের সমস্ত উত্তর সঠিক, একক কলামে DISTINCT ক্ষেত্রে বনাম GROUP BY একক কলামে on প্রতিটি ডিবি ইঞ্জিনের নিজস্ব প্রয়োগ ও অপ্টিমাইজেশন রয়েছে এবং যদি আপনি খুব সামান্য পার্থক্যের বিষয়ে যত্নশীল হন (বেশিরভাগ ক্ষেত্রে) তবে আপনাকে নির্দিষ্ট সার্ভার এবং নির্দিষ্ট সংস্করণের বিরুদ্ধে পরীক্ষা করতে হবে! বাস্তবায়ন যেমন পরিবর্তন হতে পারে ...

তবে আপনি যদি ক্যোয়ারিতে একাধিক কলাম নির্বাচন করেন তবে DISTINCT মূলত আলাদা different কারণ এই ক্ষেত্রে এটি কেবলমাত্র একটি কলামের পরিবর্তে সমস্ত সারিগুলির সমস্ত কলামের তুলনা করবে।

সুতরাং যদি আপনার মতো কিছু থাকে:

// This will NOT return unique by [id], but unique by (id,name)
SELECT DISTINCT id, name FROM some_query_with_joins

// This will select unique by [id].
SELECT id, name FROM some_query_with_joins GROUP BY id

এটি মনে করা একটি সাধারণ ভুল যে DISTINCT কীওয়ার্ডটি আপনার নির্দিষ্ট করা প্রথম কলাম দ্বারা সারিগুলি পৃথক করে, তবে DISTINCT এই পদ্ধতিতে একটি সাধারণ কীওয়ার্ড।

সুতরাং লোকেদের আপনার উপরের উত্তরগুলি সমস্ত ক্ষেত্রে সঠিক হিসাবে না নেওয়ার বিষয়ে সতর্ক থাকতে হবে ... আপনি বিভ্রান্ত হয়ে পড়তে পারেন এবং ভুল ফলাফল পেতে পারেন যখন আপনি যা চেয়েছিলেন তা অপ্টিমাইজ করা ছিল!


3
যদিও এই প্রশ্ন হল মাইএসকিউএল সম্পর্কে এটা উল্লেখ করা উচিত যে দ্বিতীয় ক্যোয়ারী কাজ করবে শুধুমাত্র মাইএসকিউএল হবে। প্রায় প্রতিটি ডিবিএমএস দ্বিতীয় বিবৃতিটি প্রত্যাখ্যান করবে কারণ এটি GROUP BY অপারেটরের একটি অবৈধ ব্যবহার।
a_horse_with_no_name

ঠিক আছে, "প্রায়" একটি সমস্যাযুক্ত সংজ্ঞা :-) আপনি যদি একটি নির্দিষ্ট ডিবিএমএস যা আপনি পরীক্ষা করে দেখেছেন যে এটি এই বিবৃতিটির জন্য একটি ত্রুটি জেনারেট করে তা বর্ণনা করা আরও বেশি সহায়ক হবে।
daniel.gindi

3
প্রারম্ভিকদের জন্য পোস্টগ্রিস, ওরাকল, ফায়ারবার্ড, ডিবি 2, এসকিউএল সার্ভার। মাইএসকিউএল: এসকিউফিল্ডল.com / #!2 / 6897c /1 পোস্টগ্রিজ : sqlfiddle.com/#!12/6897c/1 ওরাকল: sqlfiddle.com/#!12/6897c/1 এসকিউএল সার্ভার: sqlfizz.com/#!6/ 6897c / 1
a_horse_with_no_name

17

আপনি যদি পারেন তবে সবচেয়ে সহজ এবং সংক্ষিপ্ততম দিকে যান - DISTINCT কেবল আপনি যা খুঁজছেন তা আরও বেশি বলে মনে হচ্ছে কারণ এটি আপনাকে আপনার প্রয়োজনীয় উত্তরটি দেবে এবং কেবল এটিই!


7

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

SELECT DISTINCT u.profession FROM users u

সমান

SELECT u.profession FROM users u GROUP BY u.profession order by null

এর সমানSELECT profession FROM users GROUP BY profession

6

পোস্টগ্রিসের কয়েকটি অনুষ্ঠানে (অন্যান্য ডিবিএস সম্পর্কে জানেন না) ভালভাবে স্বতন্ত্র গ্রুপের চেয়ে ধীর হতে পারে।

পরীক্ষিত উদাহরণ:

postgres=# select count(*) from (select distinct i from g) a;

count 

10001
(1 row)

Time: 1563,109 ms

postgres=# select count(*) from (select i from g group by i) a;

count
10001
(1 row)

Time: 594,481 ms

http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks_I

তাই সতর্কতা অবলম্বন করা ... :)


5

দেখে মনে হচ্ছে প্রশ্নগুলি ঠিক এক নয়। কমপক্ষে মাইএসকিউএল এর জন্য।

তুলনা করা:

  1. উত্তরউইন্ড.প্রডাক্টগুলি থেকে পৃথক পৃথক পণ্য নাম বর্ণনা করুন
  2. উত্তরওয়াইন্ড থেকে প্রোডাক্ট গ্রুপ থেকে পণ্য নির্বাচন করুন name

দ্বিতীয় ক্যোয়ারী অতিরিক্ত হিসাবে "ফাইলপোর্ট ব্যবহার করে" দেয়।


1
তারা যা পায় তার ক্ষেত্রে তারা একই, তারা কীভাবে তা পায় তা নয়। একটি আদর্শ অপ্টিমাইজার তাদের একইভাবে কার্যকর করতে পারে তবে মাইএসকিউএল অপ্টিমাইজারটি আদর্শ নয়। আপনার প্রমাণের ভিত্তিতে, মনে হবে DISTINCT দ্রুততর হবে - O (n) বনাম O (n * লগ এন)।
স্কয়ারকোগ

সুতরাং, "ফাইলসোর্ট ব্যবহার করা" মূলত খারাপ জিনিস?
ভাভা

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

1
যোগ ORDER BY NULLকরার জন্য GROUP BYসংস্করণ এবং তারা একই হতে হবে।
এরিয়েল

3

ইন মাইএসকিউএল , " Group By" একটি অতিরিক্ত পদক্ষেপ ব্যবহার করে: filesort। আমি বুঝতে পারছি DISTINCTতার থেকে দ্রুততর GROUP BY, এবং এটি একটি আশ্চর্যজনক ছিল।


3

ভারী পরীক্ষার পরে আমরা এই সিদ্ধান্তে পৌঁছেছি যে গ্রুপ বাই দ্রুত

ওপোমেনগ্রোপ_ইন্টার দ্বারা গ্রুপ ( telwerken যেখানে 7,8,9,10,11,12,13 opnemergroep) গ্রুপ থেকে স্কেল_নো_ ক্যাশে ওপুনমগ্রোপ_ইন্টার নির্বাচন করুন

635 টোটাল 0.0944 সেকেন্ড ওয়েয়ারগেভ ভ্যান রেকর্ড 0 - 29 (635 টোটাল, ক্যোয়ারী ডুরডে 0.0484 সেকেন্ড)

নির্বাচন sql_no_cache স্বতন্ত্র (opnamegroep_intern) থেকে telwerken কোথায় opnemergroepইন (7,8,9,10,11,12,13)

635 টোটাল 0.2117 সেকেন্ড (প্রায় 100% ধীর) ওয়েয়ারগেভ ভ্যান রেকর্ড 0 - 29 (635 টোটাল, ক্যোয়ারী ডুরডে 0.3468 সেকেন্ড)


2

(একটি কার্যকরী নোট আরও)

এমন কিছু মামলা রয়েছে যখন আপনাকে গ্রুপের মাধ্যমে ব্যবহার করতে হয়, উদাহরণস্বরূপ আপনি যদি প্রতি নিয়োগকর্তার প্রতি কর্মচারীর সংখ্যা পেতে চান:

SELECT u.employer, COUNT(u.id) AS "total employees" FROM users u GROUP BY u.employer

যেমন একটি পরিস্থিতিতে DISTINCT u.employerঠিক কাজ করে না। সম্ভবত একটি উপায় আছে, তবে আমি এটি জানি না। (যদি কেউ DISTINCT এর সাথে কীভাবে এই জাতীয় ক্যোয়ারী তৈরি করতে জানেন তবে দয়া করে একটি নোট যুক্ত করুন!)


2

এখানে একটি সহজ পদ্ধতি যা প্রতিটি প্রশ্নের জন্য 2 টি পৃথক সময় মুদ্রণ করবে।

DECLARE @t1 DATETIME;
DECLARE @t2 DATETIME;

SET @t1 = GETDATE();
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

SET @t1 = GETDATE();
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET @t2 = GETDATE();
PRINT 'Elapsed time (ms): ' + CAST(DATEDIFF(millisecond, @t1, @t2) AS varchar);

অথবা সেট পরিসংখ্যান সময় চেষ্টা করুন (লেনদেন-এসকিউএল)

SET STATISTICS TIME ON;
SELECT DISTINCT u.profession FROM users u; --Query with DISTINCT
SELECT u.profession FROM users u GROUP BY u.profession; --Query with GROUP BY
SET STATISTICS TIME OFF;

এটি কেবল নীচের মত প্রতিটি বিবৃতি পার্স, সংকলন এবং সম্পাদন করতে প্রয়োজনীয় মিলি সেকেন্ডের সংখ্যাটি প্রদর্শন করে:

 SQL Server Execution Times:
   CPU time = 0 ms,  elapsed time = 2 ms.

1

এটি কোনও নিয়ম নয়

প্রতিটি প্রশ্নের জন্য .... আলাদা করে আলাদা করে দেখুন এবং এরপরে গ্রুপ করুন ... প্রতিটি ক্যোয়ারী শেষ করার জন্য সময়টির তুলনা করুন এবং দ্রুত ব্যবহার করুন ....

আমার প্রকল্পে একসময় আমি গোষ্ঠী এবং অন্যদের দ্বারা পৃথকভাবে ব্যবহার করি


0

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

যে কোনও ক্ষেত্রে, আপনি যদি গতির বিষয়ে উদ্বিগ্ন হন তবে কলামে একটি সূচি তৈরি করুন।


0

GROUP BY এর চেয়ে নির্বাচন বাছাই সর্বদা একই বা দ্রুত হবে। কিছু সিস্টেমে (অর্থাত্ ওরাকল) বেশিরভাগ প্রশ্নের জন্য এটি DISTINCT এর মতো হতে পারে optim অন্যদের উপর (যেমন এসকিউএল সার্ভার), এটি যথেষ্ট দ্রুততর হতে পারে।


0

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

SELECT FROM SOMETHING S WHERE S.ID IN ( SELECT DISTINCT DCR.SOMETHING_ID FROM DIFF_CARDINALITY_RELATIONSHIP DCR ) -- to keep same cardinality

একটি দ্রুত প্রতিক্রিয়া হবে:

SELECT FROM SOMETHING S WHERE EXISTS ( SELECT 1 FROM DIFF_CARDINALITY_RELATIONSHIP DCR WHERE DCR.SOMETHING_ID = S.ID )

এটি সর্বদা সম্ভব নয় তবে যখন উপলব্ধ হবে আপনি দ্রুত প্রতিক্রিয়া দেখতে পাবেন।

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