মাইএসকিউএল সূচকটি ব্যবহারের জন্য পছন্দ করার জন্য সমস্ত নির্বাচিত কলামগুলি ইন্ডেক্স করা প্রয়োজন?
এটি একটি ভারী প্রশ্ন, কারণ এমন কোনও কারণ রয়েছে যা নির্ধারণ করে যে কোনও সূচক ব্যবহার করা উচিত কিনা।
ফ্যাক্টর # 1
প্রদত্ত যে কোনও সূচকের জন্য মূল জনসংখ্যা কত? অন্য কথায়, সূচকে রেকর্ড করা সমস্ত টিপলের কার্ডিনালিটি (স্বতন্ত্র গণনা) কী?
ফ্যাক্টর # 2
আপনি কোন স্টোরেজ ইঞ্জিন ব্যবহার করছেন? সমস্ত প্রয়োজনীয় কলামগুলি কি কোনও সূচক থেকে অ্যাক্সেসযোগ্য?
এরপর কি ???
আসুন একটি সহজ উদাহরণ গ্রহণ করুন: একটি সারণী যা দুটি মান ধরে রাখে (পুরুষ এবং মহিলা)
সূচক ব্যবহারের জন্য একটি পরীক্ষা দিয়ে এই জাতীয় একটি টেবিল তৈরি করুন
USE test
DROP TABLE IF EXISTS mf;
CREATE TABLE mf
(
id int not null auto_increment,
gender char(1),
primary key (id),
key (gender)
) ENGINE=InnODB;
INSERT INTO mf (gender) VALUES
('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
('M'),('M'),('M'),('M'),('F'),('F'),('M'),('M'),
('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
('F'),('M'),('M'),('M'),('M'),('M'),('M'),('M');
ANALYZE TABLE mf;
EXPLAIN SELECT gender FROM mf WHERE gender='F';
EXPLAIN SELECT gender FROM mf WHERE gender='M';
EXPLAIN SELECT id FROM mf WHERE gender='F';
EXPLAIN SELECT id FROM mf WHERE gender='M';
পরীক্ষা ইনোডিবি
mysql> USE test
Database changed
mysql> DROP TABLE IF EXISTS mf;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE mf
-> (
-> id int not null auto_increment,
-> gender char(1),
-> primary key (id),
-> key (gender)
-> ) ENGINE=InnoDB;
Query OK, 0 rows affected (0.07 sec)
mysql> INSERT INTO mf (gender) VALUES
-> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
-> ('M'),('M'),('M'),('M'),('F'),('F'),('M'),('M'),
-> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
-> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
-> ('F'),('M'),('M'),('M'),('M'),('M'),('M'),('M');
Query OK, 40 rows affected (0.06 sec)
Records: 40 Duplicates: 0 Warnings: 0
mysql> ANALYZE TABLE mf;
+---------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+---------+----------+----------+
| test.mf | analyze | status | OK |
+---------+---------+----------+----------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT gender FROM mf WHERE gender='F';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| 1 | SIMPLE | mf | ref | gender | gender | 2 | const | 3 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT gender FROM mf WHERE gender='M';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| 1 | SIMPLE | mf | ref | gender | gender | 2 | const | 37 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT id FROM mf WHERE gender='F';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| 1 | SIMPLE | mf | ref | gender | gender | 2 | const | 3 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT id FROM mf WHERE gender='M';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| 1 | SIMPLE | mf | ref | gender | gender | 2 | const | 37 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
mysql>
মাইসাম পরীক্ষা
mysql> USE test
Database changed
mysql> DROP TABLE IF EXISTS mf;
Query OK, 0 rows affected (0.00 sec)
mysql> CREATE TABLE mf
-> (
-> id int not null auto_increment,
-> gender char(1),
-> primary key (id),
-> key (gender)
-> ) ENGINE=MyISAM;
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO mf (gender) VALUES
-> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
-> ('M'),('M'),('M'),('M'),('F'),('F'),('M'),('M'),
-> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
-> ('M'),('M'),('M'),('M'),('M'),('M'),('M'),('M'),
-> ('F'),('M'),('M'),('M'),('M'),('M'),('M'),('M');
Query OK, 40 rows affected (0.00 sec)
Records: 40 Duplicates: 0 Warnings: 0
mysql> ANALYZE TABLE mf;
+---------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+---------+---------+----------+----------+
| test.mf | analyze | status | OK |
+---------+---------+----------+----------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT gender FROM mf WHERE gender='F';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| 1 | SIMPLE | mf | ref | gender | gender | 2 | const | 3 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT gender FROM mf WHERE gender='M';
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
| 1 | SIMPLE | mf | ref | gender | gender | 2 | const | 36 | Using where; Using index |
+----+-------------+-------+------+---------------+--------+---------+-------+------+--------------------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT id FROM mf WHERE gender='F';
+----+-------------+-------+------+---------------+--------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+--------+---------+-------+------+-------------+
| 1 | SIMPLE | mf | ref | gender | gender | 2 | const | 3 | Using where |
+----+-------------+-------+------+---------------+--------+---------+-------+------+-------------+
1 row in set (0.00 sec)
mysql> EXPLAIN SELECT id FROM mf WHERE gender='M';
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
| 1 | SIMPLE | mf | ALL | gender | NULL | NULL | NULL | 40 | Using where |
+----+-------------+-------+------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)
mysql>
InnoDB এর জন্য বিশ্লেষণ
যখন ডেটা ইনোডিবি হিসাবে লোড করা হয়েছিল, দয়া করে নোট করুন যে চারটি EXPLAIN
পরিকল্পনাই gender
সূচকটি ব্যবহার করেছিল । তৃতীয় এবং চতুর্থ EXPLAIN
পরিকল্পনাগুলি gender
অনুরোধ করা ডেটা থাকলেও সূচকটি ব্যবহার করেছিল id
। কেন? কারণ id
রয়েছে PRIMARY KEY
এবং সব মাধ্যমিক সূচী আছে রেফারেন্স পয়েন্টার ফিরে PRIMARY KEY
(মাধ্যমে gen_clust_index )।
মাইআইএসএএম এর জন্য বিশ্লেষণ
যখন ডেটা মাইআইএসএএম হিসাবে লোড করা হয়েছিল, দয়া করে নোট করুন যে প্রথম তিনটি EXPLAIN
পরিকল্পনা gender
সূচি ব্যবহার করেছিল । চতুর্থ EXPLAIN
পরিকল্পনায় ক্যোয়ারী অপ্টিমাইজার মোটেও একটি সূচক ব্যবহার না করার সিদ্ধান্ত নিয়েছে। পরিবর্তে এটি একটি পূর্ণ টেবিল স্ক্যান বেছে নিয়েছে। কেন?
ডিবিএমএস নির্বিশেষে, কোয়েরি অপ্টিমাইজারগুলি একটি খুব সাধারণ নিয়ম-এর-থাম্বটিতে কাজ করে: যদি কোনও সূচকটি পরীক্ষার জন্য পরীক্ষার জন্য প্রার্থী হিসাবে স্ক্রিন করা হয় এবং ক্যোরি অপটিমাইজার গণনা করে যে এটি অবশ্যই মোট সংখ্যার 5% এর বেশি দেখতে হবে সারণীতে সারি:
- পুনরুদ্ধারের জন্য প্রয়োজনীয় সমস্ত কলামগুলি নির্বাচিত সূচীতে থাকলে একটি পূর্ণ সূচক স্ক্যান করা হয়
- অন্যথায় একটি সম্পূর্ণ টেবিল স্ক্যান
উপসংহার
আপনার যদি সঠিক কভারিং সূচক না থাকে বা যদি কোনও প্রদত্ত টুপলের মূল জনসংখ্যা সারণির 5% এর বেশি হয় তবে ছয়টি জিনিস অবশ্যই ঘটবে:
- অনুধাবনে আসুন যে আপনাকে অবশ্যই প্রশ্নগুলি প্রোফাইল করতে হবে
- এই অনুসন্ধানগুলি থেকে সমস্ত
WHERE
, GROUP BY
এবং অর্ডার বাই-ক্লজগুলি সন্ধান করুন
- এই ক্রমে সূচকগুলি সূচনা করুন
WHERE
স্থির মান সহ ধারা কলাম
GROUP BY
কলাম
ORDER BY
কলাম
- পূর্ণ টেবিল স্ক্যানগুলি এড়িয়ে চলুন (কোনও বুদ্ধিমান
WHERE
ধারার অভাবে প্রশ্নগুলি )
- খারাপ কী জনসংখ্যা এড়িয়ে চলুন (বা কমপক্ষে সেই খারাপ কী জনসংখ্যা ক্যাশে করুন)
- সেরা মাইএসকিউএল সংগ্রহস্থল ইঞ্জিন (স্থির InnoDB বা MyISAM টেবিল জন্য)
আমি অতীতে এই 5% নিয়মের সম্পর্কে লিখেছি:
আপডেট 2012-11-14 13:05 ইডিটি
আমি আপনার প্রশ্ন এবং মূল এসও পোস্টে ফিরে তাকান । তারপরে, আমি আমার Analysis for InnoDB
আগে উল্লিখিত আমার সম্পর্কে ভেবেছিলাম । এটি person
টেবিলের সাথে মিলে যায় । কেন?
উভয় টেবিলের জন্য mf
এবংperson
- স্টোরেজ ইঞ্জিনটি ইনোডিবি
- প্রাথমিক কী
id
- সারণী অ্যাক্সেস মাধ্যমিক সূচক দ্বারা হয়
- যদি টেবিলটি মাইআইএসএএম হয় তবে আমরা সম্পূর্ণ ভিন্ন
EXPLAIN
পরিকল্পনা দেখতে পেতাম
এখন, তাই প্রশ্ন থেকে ক্যোয়ারী তাকান: select * from person order by age\G
। যেহেতু কোনও WHERE
ধারা নেই, আপনি স্পষ্টভাবে একটি পূর্ণ টেবিল স্ক্যানের দাবি করেছেন । টেবিলের ডিফল্ট সাজানোর ক্রমটি (id
PRYARY KEY) দ্বারা হবে কারণ এটি অটো_সংশ্লিষ্ট এবং জেন_ ক্লাস্ট_ইন্ডেক্স (ওরফে ক্লাস্টারড ইনডেক্স) অভ্যন্তরীণ রোউইড দ্বারা আদেশ করা হয়েছে । আপনি যখন সূচক দ্বারা আদেশ করেছেন, তখন মনে রাখবেন যে ইনোডিবি মাধ্যমিক সূচকগুলিতে প্রতিটি সূচী প্রবেশের সাথে সারি সংযুক্ত থাকে। এটি প্রতিবার সম্পূর্ণ সারি অ্যাক্সেসের অভ্যন্তরীণ প্রয়োজনীয়তা তৈরি করে।
ORDER BY
ইনোডিবি সূচকগুলি কীভাবে সংগঠিত হয় সে সম্পর্কে যদি আপনি এই বিষয়গুলি উপেক্ষা করেন তবে একটি ইনোডিবি টেবিল সেট আপ করা বরং একটি কঠিন কাজ হতে পারে।
আপনি এই স্পষ্টতই একটি সম্পূর্ণ টেবিল স্ক্যানের দাবি করেছেন, সুতরাং এই এস ক্যোয়ারিতে ফিরে যাওয়া, মাইএসকিউএল ক্যোরি অপটিমাইজার সঠিক কাজটি করেছিলেন (বা কমপক্ষে, সর্বনিম্ন প্রতিরোধের পথটি বেছে নিয়েছে) IM যখন এটি ইনোডিবি এবং এসও ক্যোয়ারীর কথা আসে, একটি সম্পূর্ণ টেবিল স্ক্যান করা খুব সহজ এবং তারপরে কিছু filesort
প্রতিটি গৌণ সূচকের প্রবেশের জন্য জেন_ক্লাস্ট_ইন্ডেক্সের মাধ্যমে একটি পূর্ণ সূচী স্ক্যান এবং একটি সারি লুকে দেখার চেয়ে।
আমি সূচক ইঙ্গিতগুলি ব্যবহারের পক্ষে সমর্থনকারী নই কারণ এটি এক্সপ্ল্যান পরিকল্পনাটি উপেক্ষা করে। তবুও, আপনি যদি সত্যই আপনার তথ্য InnoDB এর চেয়ে ভাল জানেন তবে আপনাকে সূচক ইঙ্গিতগুলি অবলম্বন করতে হবে, বিশেষত কোনও WHERE
দফা নেই এমন প্রশ্নের সাথে ।
আপডেট 2012-11-14 14:21 ইডিটি
মাইএসকিউএল ইন্টার্নালগুলি বোঝার বই অনুসারে
পৃষ্ঠা 202 অনুচ্ছেদ 7 নিম্নলিখিতটি বলেছে:
ডেটাগুলি একটি ক্লাস্টারড ইনডেক্স নামে একটি বিশেষ কাঠামোতে সংরক্ষণ করা হয় , যা মূল-মূল হিসাবে কাজ করা প্রাথমিক কী সহ একটি বি-ট্রি এবং ডেটা অংশে প্রকৃত রেকর্ড (পয়েন্টারের পরিবর্তে) থাকে। সুতরাং, প্রতিটি InnoDB টেবিলের একটি প্রাথমিক কী থাকতে হবে। যদি কোনও সরবরাহ না করা হয় তবে একটি বিশেষ সারি আইডি কলাম প্রাথমিকভাবে ব্যবহারকারী হিসাবে প্রদর্শিত হয় না যা প্রাথমিক কী হিসাবে কাজ করার জন্য যুক্ত করা হয় to একটি মাধ্যমিক কী প্রাথমিক কীটির মান সংরক্ষণ করবে যা রেকর্ডটি সনাক্ত করে। বি-ট্রি কোড ইনোএনবেস / বিটিআর / বিটিআর0 বিটিআর.সি . তে পাওয়া যাবে ।
এই কারণেই আমি আগে বলেছি: প্রতিটি সেকেন্ডারি সূচকের প্রবেশের জন্য জেন_ক্লাস্ট_আইডেক্সের মাধ্যমে একটি পূর্ণ সূচী স্ক্যান এবং একটি সারি সন্ধানের চেয়ে একটি পূর্ণ টেবিল স্ক্যান এবং তারপরে কিছু ফাইলসোর্ট করা আরও সহজ । InnoDB প্রতিবার একটি ডাবল ইনডেক্স লুকআপ করতে চলেছে । এটি একদম নির্মম শোনায় তবে এটি কেবল সত্য। আবার, WHERE
ধারাটির অভাব বিবেচনা করুন । এটি নিজেই, সম্পূর্ণ টেবিল স্ক্যান করার জন্য মাইএসকিউএল কোয়েরি অপ্টিমাইজারের ইঙ্গিত।
FOR ORDER BY
(যা এই প্রশ্নের নির্দিষ্ট ক্ষেত্রে)। প্রশ্নটি বলেছিল যে এক্ষেত্রে স্টোরেজ ইঞ্জিনটি ছিলInnoDB
(এবং মূল এসও প্রশ্নটি দেখায় যে 10 কে সারিগুলি 8 টি আইটেমের মধ্যে মোটামুটি সমানভাবে বিতরণ করা হয়েছে, কার্ডিনালিটি এখানে কোনও সমস্যা হওয়া উচিত নয়)। দুঃখের বিষয়, আমি মনে করি না যে এটি প্রশ্নের উত্তর দেয়।