মাঝেমধ্যে ধীর অনুসন্ধানের কারণ?


16

আমরা উইন্ডোজ সার্ভার ২০০৮ আর 2 এ মাইএসকিউএল 5.1 চালাচ্ছি।

আমরা দেরীতে আমাদের ডাটাবেসে কিছু ডায়াগনস্টিক করছি এবং কিছু বিরক্তিকর নিদর্শন পেয়েছি যা আমরা ব্যাখ্যা করতে পারি না । লগতে আমরা কিছু কোড যুক্ত করেছি যখন আমাদের জিজ্ঞাসাগুলি ছিল যা দীর্ঘ সময় (> 2000 মিমি) নিয়েছিল। ফলাফলগুলি বিস্ময়কর ছিল (এবং সম্ভবত আমাদের ডেডলকের জন্য একটি ব্যাখ্যা)।

মাঝে মাঝে অনুসন্ধানগুলি, সাধারণত এটি খুব কম সময় নেয় (<10 মিমি), 4 থেকে 13 সেকেন্ড সময় নেয়। স্পষ্টরূপে বলতে গেলে, এগুলি এমন প্রশ্নগুলি যা ক্রমাগত চলতে থাকে (কয়েক সেকেন্ডে কয়েকবার) এবং এই ক্যোয়ারির সময় স্পাইকগুলিতে ভুগছে না।

আমরা আমাদের সূচিগুলি পেরিয়ে গিয়েছি কোনও সুস্পষ্ট ভুল খুঁজছি এবং খুব ভাগ্য পাইনি।

হালনাগাদ

লোক টেবিল:

| people | CREATE TABLE `people` (
`people_id` bigint(20) NOT NULL AUTO_INCREMENT,
`company_id` bigint(20) NOT NULL,
`name` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`temp_password` varchar(10) DEFAULT NULL,
`reset_password_hash` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`phone` varchar(32) DEFAULT NULL,
`mobile` varchar(32) DEFAULT NULL,
`iphone_device_id` varchar(160) DEFAULT NULL,
`iphone_device_time` datetime DEFAULT NULL,
`last_checkin` datetime DEFAULT NULL,
`location_lat` double DEFAULT NULL,
`location_long` double DEFAULT NULL,
`gps_strength` smallint(6) DEFAULT NULL,
`picture_blob_id` bigint(20) DEFAULT NULL,
`authority` int(11) NOT NULL DEFAULT '0',
`active` tinyint(1) NOT NULL DEFAULT '1',
`date_created` datetime NOT NULL,
`last_login` datetime NOT NULL,
`panic_mode` tinyint(1) NOT NULL DEFAULT '0',
`battery_level` double DEFAULT NULL,
`battery_state` varchar(32) DEFAULT NULL,
PRIMARY KEY (`people_id`),
KEY `email` (`email`),
KEY `company_id` (`company_id`),
KEY `iphone_device_id` (`iphone_device_id`),
KEY `picture_blob_id` (`picture_blob_id`),
CONSTRAINT `people_ibfk_1` FOREIGN KEY (`company_id`) REFERENCES `companies` (`company_id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `people_ibfk_2` FOREIGN KEY (`picture_blob_id`) REFERENCES `blobs` (`blob_id`) ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=4658 DEFAULT CHARSET=utf8 |

ইনডেক্সে:

+--------+------------+------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table  | Non_unique | Key_name         | Seq_in_index | Column_name      | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+
| people |          0 | PRIMARY          |            1 | people_id        | A         |        3502 |     NULL | NULL   |      | BTREE      |         |
| people |          1 | email            |            1 | email            | A         |        3502 |     NULL | NULL   | YES  | BTREE      |         |
| people |          1 | company_id       |            1 | company_id       | A         |        3502 |     NULL | NULL   |      | BTREE      |         |
| people |          1 | iphone_device_id |            1 | iphone_device_id | A         |        3502 |     NULL | NULL   | YES  | BTREE      |         |
| people |          1 | picture_blob_id  |            1 | picture_blob_id  | A         |        3502 |     NULL | NULL   | YES  | BTREE      |         |
+--------+------------+------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+

আমাদের সার্ভারে টেবিলটিতে আমাদের 5000 ডলার সারি রয়েছে যা আমাদের সমস্যা দিচ্ছে।


1
এমন কিছু আছে যা আপনি আগের দুটি প্রশ্নে এখনও দেখান নি। দয়া করে এই প্রশ্নটিতে তিনটি যুক্ত করুন (3) টিজিংস: 1) টেবিলের লোক তৈরি করুন \ জি 2) লোকদের থেকে সূচকগুলি দেখান; 3) নির্বাচন করুন COUNT (1) লোক থেকে;
রোল্যান্ডোমাইএসকিউএলডিবিএ

@ রোল্যান্ডোমাইএসকিউএলডিবিএ আগামীকাল কাজে আসার সাথে সাথে আমি এটি করব। চিয়ার্স :)
রেড ব্লুথিং

আমি আমার উত্তর আপডেট। দয়া করে পড়ুন !!!
রোল্যান্ডোমাইএসকিউএলডিবিএ

@ রোল্যান্ডোমাইএসকিউএলডিবিএ ধন্যবাদ :)। এখনও এই জিনিস পার্সিং। আমি আপনাকে জানাব যে আমরা কীভাবে চলেছি।
রেড ব্লুথিং

উত্তর:


14

আপনার আগের দুটি প্রশ্নে আপডেটের প্রশ্নাবলী ( প্রশ্নাবলি 1 , প্রশ্ন 2) ) সারি স্তরটি লকিংয়ের মাধ্যমে প্রাইমারী কে দ্বারা টেবিলটিকে 'লোক' মারছে। 6 জুন, ২০১১ 10:03 পূর্বাহ্নে প্রশ্ন1-এ আমি এটিই বলেছি

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

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

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

যদি 'লোকেরা' টেবিলটিতে প্রচুর অ-অনন্য সূচক থাকে তবে টেবিল স্পেসে প্রচুর পরিমাণে সূচী পৃষ্ঠাগুলি তৈরি করার পাশাপাশি ছোট ছোট সারি লকগুলি আপনার কাছে সময়ে সময়ে ছড়িয়ে রাখার জন্য প্রস্তুত করুন।

এখানে আরও একটি কারণ রয়েছে যা স্পষ্ট নয়: কী জনসংখ্যা

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

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

আপডেট ২০১১-০6-২৪ 22:19

প্রশ্ন থেকে প্রশ্ন 1

UPDATE people SET company_id = 1610, name = '<name>', password = '<hash>',
temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@yahoo.com',
phone = NULL, mobile = '<phone>', iphone_device_id = 'android:<id>-<id>',
iphone_device_time = '2011-06-06 05:35:09', last_checkin = '2011-06-06 05:24:42',
location_lat = <lat>, location_long = -<lng>, gps_strength = 3296,
picture_blob_id = 1190,
authority = 1, active = 1, date_created = '2011-04-13 20:21:20',
last_login = '2011-06-06 05:35:09', panic_mode = 0,
battery_level = NULL, battery_state = NULL WHERE people_id = 3125

UPDATE people SET company_id = 1610, name = '<name>', password = '<hash>',
temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@yahoo.com',
phone = NULL, mobile = '<phone>', iphone_device_id = 'android:<id>-<id>-<id>-<id>',
iphone_device_time = '2011-06-06 05:24:42', last_checkin = '2011-06-06 05:35:07',
location_lat = <lat>, location_long = -<lng>, gps_strength = 3296,
picture_blob_id = 1190,
authority = 1, active = 1, date_created = '2011-04-13 20:21:20',
last_login = '2011-06-06 05:35:09', panic_mode = 0,
battery_level = NULL, battery_state = NULL WHERE people_id = 3125

ইভেন্টের ক্রমটি চিত্রিত করুন

  1. প্রাথমিক কী দ্বারা সারিটি সন্ধান করুন
  2. সারি এবং ক্লাস্টার্ড সূচক লক করুন
  3. আপডেট হওয়া সমস্ত কলামের জন্য এমভিসিসি ডেটা তৈরি করুন
  4. চারটি কলাম ইনডেক্স করা হয়েছে (ইমেল, কোম্পানী_আইডি, আইফোন_দেহী_আইডি, ছবি_ব্লব_আইডি)
  5. প্রতিটি সূচকের বিটিআরই পরিচালনা প্রয়োজন
  6. একই লেনদেনের জায়গার মধ্যে, 1-5 টি পদক্ষেপ একই সারিতে পুনরাবৃত্তি করার চেষ্টা করছে, একই কলামগুলি আপডেট করছে (উভয় প্রশ্নের মধ্যে একই ইমেল করুন, উভয় প্রশ্নের মধ্যে একইভাবে কোম্পানী_আইড, চিত্র_ব্লব_আইডি উভয় প্রশ্নের মধ্যে একই, আইফোন_দেখানো_আইডি)

প্রশ্ন 2 থেকে প্রশ্নসমূহ

UPDATE people SET iphone_device_id=NULL
WHERE iphone_device_id='iphone:<device_id_blah>' AND people_id<>666;

UPDATE people SET company_id = 444, name = 'Dad', password = '<pass>',
temp_password = NULL, reset_password_hash = NULL, email = '<redacted>@gmail.com',
phone = NULL, mobile = NULL, iphone_device_id = 'iphone:<device_id_blah>',
iphone_device_time = '2011-06-06 19:12:29', last_checkin = '2011-06-07 02:49:47',
location_lat = <lat>, location_long = <lng>, gps_strength = 66,
picture_blob_id = 1661,
authority = 1, active = 1, date_created = '2011-03-20 19:18:34',
last_login = '2011-06-07 11:15:01', panic_mode = 0, battery_level = 0.55,
battery_state = 'unplugged' WHERE people_id = 666;

এই দুটি ক্যোয়ারী আরও বিভ্রান্তিকর কারণ প্রথম ক্যোয়ারী _ 666 জন ছাড়া সমস্ত কিছু আপডেট করছে। শত শত সারিটি কেবলমাত্র প্রথম ক্যোয়ারির সাথে বেদনাদায়কভাবে লক করা হচ্ছে। দ্বিতীয় ক্যোয়ারী ইভেন্টগুলি 5 সিকোয়েন্স চালিয়ে লোক_আইডি 666 আপডেট করছে। প্রথম ক্যোয়ারী লোক_আইডি except 666 ব্যতীত প্রতিটি সারিতে একই একই 5 ইভেন্টের ক্রম চালাচ্ছে তবে আইফোন_ডভাইস_আইডির সূচকটি দুটি পৃথক ক্যোয়ারী সহ একটি স্বীকৃতিপূর্ণ কোর্সে রয়েছে। প্রথম আসুন-প্রথম পরিবেশন ভিত্তিতে বিটিআরই পৃষ্ঠাগুলিতে কারওর লক লক হবে।

একটি সংঘর্ষের কোর্সে এই দুটি জোড়া প্রশ্নের মুখোমুখি হয়ে একই সূত্রের মধ্যে একই বিটিআরই পৃষ্ঠাগুলি লক করতে সম্ভবত ইনোডিবি বা যে কোনও এসিডি-অনুবর্তী আরডিবিএমএসের জন্য অন্ত্রের রেঞ্চিং অভিজ্ঞতা হতে পারে। সুতরাং, সূচকের মন্থরতা হ'ল এই জোড়া প্রশ্নের ক্যারিয়ারের গন্তব্য, যদি আপনি গ্যারান্টি দিতে না পারেন যে প্রশ্নগুলি অটোকোমিট = 1 দিয়ে চলছে বা নোংরা পড়ার অনুমতি দিয়ে (যদিও এ জাতীয় সংঘর্ষগুলি এমডিসি-র জন্য READ-COMMITTED এবং READ-UNCOMMITED করে তোলে)।

আপডেট 2011-06-15 10:29

@ রেডব্লিউথিং: প্রশ্ন 2 এর প্রশ্নের মধ্যে, প্রথম ক্যোয়ারীটি একটি ব্যাপ্তি ক্যোয়ারী, সুতরাং প্রচুর সারি লকগুলি প্রাপ্ত করা হচ্ছে। এছাড়াও লক্ষ্য করুন যে উভয় জিজ্ঞাসা একই স্পেস আইডি 0 পৃষ্ঠা নং 4611 এন বিট 152 লিমিটেড প্রাইমারি কে, ওরফে ক্লাস্টার ইনডেক্সে লক করার চেষ্টা করছে notice

আপনার অ্যাপটি খুব কমপক্ষে, আপনার প্রত্যাশিত ইভেন্টগুলির ধারাবাহিকের উপর ভিত্তি করে চলমান রয়েছে তা নিশ্চিত করার জন্য, আপনি চেষ্টা করতে পারেন এমন দুটি ভিন্ন বিকল্প রয়েছে:

বিকল্প 1) এই টেবিলটি মাইআইএসএমে রূপান্তর করুন (কমপক্ষে একটি ডেভলপমেন্ট সার্ভারে)। প্রতি আপডেট, INSERT, এবং মোছা প্রথম আসুন, প্রথম পরিবেশন ভিত্তিতে একটি পূর্ণ টেবিল লক চাপিয়ে দেবে।

বিকল্প 2) সিরিয়ালিজেবল বিচ্ছিন্নতা স্তরটি ব্যবহার করে দেখুন । এটি SHARED মোডে সমস্ত উদ্দেশ্যযুক্ত সারিগুলি লক করবে।

আপনার প্রত্যাশিত ইভেন্টগুলির ক্রমটি এই দুটি বিকল্প বিকল্প ব্যবহার করে ভেঙে যাবে বা সফল হবে। যদি এই দুটি অপশনই ব্যর্থ হয়, তবে আপনাকে আপনার অ্যাপ্লিকেশনটি সন্ধান করতে হবে এবং আপনার প্রশ্নের প্রয়োগের আদেশটিকে অগ্রাধিকার দেবে। একবার আপনি এই অগ্রাধিকারটি প্রতিষ্ঠিত করলে, আপনি কেবল এই বিকল্পগুলি পূর্বাবস্থায় ফিরিয়ে আনতে পারেন (বিকল্প 1 এর জন্য, InnoDB এ ফিরে যান, বিকল্প 2 এর জন্য, ডিফল্ট বিচ্ছিন্নতা স্তরে ফিরে যান [সিরিয়াল ব্যবহার বন্ধ করুন])।


@ রোল্যান্ডোমাইএসকিউএলডিবিএ আপনার জিজ্ঞাসিত বিবরণ সহ আমি আমাদের প্রশ্ন আপডেট করেছি।
রেড ব্লুথিং

@ রোল্যান্ডোমাইএসকিউএলডিবিএ এ সম্পর্কে আরও একবার দেখার জন্য ধন্যবাদ। আমি ভাবছিলাম, আপনি প্রশ্ন 2 এর জন্য মন্তব্য করেছেন, কেন প্রথম জিজ্ঞাসাটি কয়েকশো সারি লক করবে? এটি কি কেবল ডিভাইস আইডির সাথে মিলে থাকা 666 টি সারি লক করবে না? (অর্থাত্ একটি একক সারি)
রেড ব্লুথিং

@ রোল্যান্ডোমাইএসকিউএলডিবিএ প্রশ্ন 1 থেকে আপনার পরামর্শের ভিত্তিতে, আমরা আমাদের স্বতঃপাদন সেটিংস পরীক্ষা করেছিলাম এবং নিশ্চিত হয়েছি যে এটি চালু আছে।
রেড ব্লুথিং

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

@ রোল্যান্ডোমাইএসকিউএলডিবিএ +1 এবং আপনার সমস্ত পরামর্শের জন্য ধন্যবাদ। সমস্যাটি সমাধানের জন্য আমরা বিচ্ছিন্নতা স্তরটি পরিবর্তন করি না। পরিবর্তে আমরা প্রশ্ন 2 এর জন্য আংশিক ক্ষেত্রের আপডেট করেছি এবং আপডেটের পথে কোনও প্রশ্নকে অপ্টিমাইজ করেছি। ভাল খবর! আর কোনও অচলাবস্থা নেই। :)
রেড ব্লুথিং

3

ভেরিয়েবলগুলি 'ইনডোডব%' পছন্দ করুন; - বিশেষত, যদি ডেটা এবং সূচিগুলি কেবল বাফার পুলের আকারে না পৌঁছে, তবে আপনি ডিস্কটিকে আগের চেয়ে অনেক শক্ত করে আঘাত করতে পারেন। আই / ও হ'ল বড় পারফরম্যান্স কিলার।

আপনার ক্ষেত্রগুলির বেশিরভাগই প্রয়োজনের দ্বিগুণ। বিগিন্ট (8 বাইট) বেশিরভাগ আইডির জন্য ওভারকিল। 5000 সারিগুলির জন্য কেবলমাত্র একটি ছোট ছোট UNSIGNED (65K এর সীমা, মাত্র 2 বাইট) needs বা নিরাপত্তার মার্জিনের জন্য মিডিয়ামট ব্যবহার করুন use

ডাবল 8 বাইট ব্যয়ে আপনাকে 16 টি গুরুত্বপূর্ণ সংখ্যা দেয়। ব্যাটারি-লেভেলটিতে 2 টিরও বেশি উল্লেখযোগ্য অঙ্কের নির্ভুলতা থাকতে পারে? ফ্লোটে 4 বাইট লাগে

আমার বক্তব্যটি এখানে "ছোট -> আরও ক্যাশেযোগ্য -> দ্রুত"।

দয়া করে আমাদের ধীর অনুসন্ধানগুলি দেখান; হ'ল হঠাৎ ধীর হয়ে গেছে এমন কয়েকটি অন্তত ones আমরা এগুলি ছাড়া কেবল অনুমান করতে পারি। স্লোল্যাগটি চালু করুন এবং দীর্ঘ_ ক্যোয়ারী_টাইম = 1 সেট করুন; এগুলি ধীরতম অনুসন্ধানগুলি অনুসন্ধানে সহায়তা করবে।

আপনি কি "যৌগিক" সূচকগুলির সুবিধা বুঝতে পারছেন?

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