আমি যখন কলামগুলি সূচী করি তখন কেন এই স্ক্লাইট কোয়েরিটি অনেক ধীর হয়?


14

আমার কাছে দুটি টেবিলের সাথে একটি স্ক্লাইট ডাটাবেস রয়েছে, যার প্রতিটিতে 50,000 সারি রয়েছে (জাল) লোকের নাম রয়েছে containing উভয় টেবিলের মধ্যে প্রচলিত কতগুলি নাম (প্রদত্ত নাম, মাঝারি প্রাথমিক, উপাধি) রয়েছে তা সন্ধান করার জন্য আমি একটি সাধারণ ক্যোয়ারী তৈরি করেছি:

select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;

যখন প্রাথমিক কীগুলি (এই ক্যোয়ারীর সাথে অপ্রাসঙ্গিক) ব্যতীত কোনও সূচক নেই, এটি দ্রুত চলে:

[james@marlon Downloads] $ time sqlite3 generic_data_no_indexes.sqlite "select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;"
131

real    0m0.115s
user    0m0.111s
sys     0m0.004s

তবে আমি যদি প্রতিটি টেবিলের তিনটি কলামে ইনডেক্স যুক্ত করি (সমস্ত ছয়টি সূচক):

CREATE INDEX `idx_uk_givenname` ON `fakenames_uk` (`givenname` )
//etc.

তারপর এটি বেদনাদায়ক ধীরে ধীরে চলে:

[james@marlon Downloads] $ time sqlite3 generic_data.sqlite "select count(*) from fakenames_uk inner join fakenames_usa on fakenames_uk.givenname=fakenames_usa.givenname and fakenames_uk.surname=fakenames_usa.surname and fakenames_uk.middleinitial=fakenames_usa.middleinitial;"
131

real    1m43.102s
user    0m52.397s
sys     0m50.696s

এর কোন ছড়া বা যুক্তি আছে কি?

EXPLAIN QUERY PLANসূচি ছাড়াই সংস্করণটির ফলাফল এখানে :

0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING AUTOMATIC COVERING INDEX (middleinitial=? AND surname=? AND givenname=?)

এটি সূচকের সাথে রয়েছে:

0|0|0|SCAN TABLE fakenames_uk
0|1|1|SEARCH TABLE fakenames_usa USING INDEX idx_us_middleinitial (middleinitial=?)

1
আপনার সূচিগুলি আচ্ছাদন করছে না। দেখা যাচ্ছে আপনি পৃথকভাবে প্রতিটি কলামকে সূচি দিচ্ছেন। যখন আপনি একটি সূচক তিনটি কলাম ধারণকারী একটি আচ্ছাদন সূচক তৈরি করুন (কি হবে middleinitial, surnameএবং givenname)?
র‌্যান্ডল্ফ ওয়েস্ট

@ র‌্যান্ডফ ওয়েস্ট আমি বুঝতে চাইছি আপনি কী বোঝাতে চেয়েছিলেন তবে আপনি সঠিক পরিভাষাটি ব্যবহার করছেন না: একটি "কভারিং ইনডেক্স" এমন একটি যা কলামগুলিও নির্বাচিত রয়েছে includes উদাহরণস্বরূপ, ক্যোয়ারির জন্য SELECT c FROM t WHERE a=1 AND b=2, সূচকটি t(a,b,c)আচ্ছাদন করছে তবে t(a,b)তা নয়। সূচকগুলি coveringেকে দেওয়ার সুবিধাটি হ'ল পুরো ক্যোয়ারির ফলাফলটি সরাসরি সূচকের বাইরে টানা যায়, যেখানে অ-আচ্ছাদন সূচকগুলি দ্রুত প্রাসঙ্গিক সারিগুলি সন্ধান করে তবে মানগুলি খুঁজে বের করার জন্য এটি এখনও প্রধান টেবিলের ডেটা উল্লেখ করতে হবে।
আর্থার টাচকা

উত্তর:


15

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

যদি কোনও সূচক থাকে, ডাটাবেসগুলি সূচীতে দ্রুত কোনও ম্যাচ সন্ধান করতে পারে এবং তারপরে প্রয়োজনীয় অন্য যে কোনও কলামের মান পেতে সংশ্লিষ্ট টেবিল সারিতে যেতে পারে।

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

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

এই ক্যোয়ারীটির গতি বাড়ানোর জন্য, এই সূচিটি স্থায়ীভাবে তৈরি করুন, যাতে কোনও অস্থায়ী তৈরির প্রয়োজন হয় না:

CREATE INDEX uk_all_names ON fakenames_uk(surname, givenname, middleinitial);

EXPLAIN QUERY PLAN
SELECT count(*)
FROM fakenames_uk
JOIN fakenames_usa USING (givenname, middleinitial, surname);

0|0|1|SCAN TABLE fakenames_usa
0|1|0|SEARCH TABLE fakenames_uk USING COVERING INDEX uk_all_names (surname=? AND givenname=? AND middleinitial=?)

এই সূচকের surnameআর দরকার নেই কারণ এই কলামে যে কোনও লুকের জন্য থ্রি-কলাম সূচি ব্যবহার করা যেতে পারে। আপনি কেবলমাত্র এই কলামে লুকআপ করতে গেলে
সূচকটি কার্যকর givennameহতে পারে। উপরের
সূচকটি middleinitialসর্বদা নিরর্থক: 26 টি সম্ভাব্য মানগুলির মধ্যে একটির অনুসন্ধান করে এমন একটি কোয়েরি যদি কেবলমাত্র পুরো টেবিলটি স্ক্যান করে।

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