একটি বড় 220 মিলিয়ন সারি টেবিলের (9 গিগের ডেটা) কোয়েরি কীভাবে করা যায়?


31

সমস্যাটি:

আমাদের একটি সামাজিক সাইট রয়েছে যেখানে সদস্যরা একে অপরের সাথে সামঞ্জস্য বা মিলের জন্য রেট দিতে পারে। এই user_match_ratingsটেবিলটিতে 220 মিলিয়ন সারি রয়েছে (9 জিগ ডেটা বা সূচীতে প্রায় 20 জিগ)। এই টেবিলের বিরুদ্ধে অনুসন্ধানগুলি নিয়মিতভাবে স্লো.লগ (থ্রেশহোল্ড> 2 সেকেন্ড) এ প্রদর্শিত হয় এবং এটি সিস্টেমে সর্বাধিক ঘন ঘন লগ করা ধীর ক্যোয়ারী:

Query_time: 3  Lock_time: 0  Rows_sent: 3  Rows_examined: 1051
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 395357 group by rating;"

Query_time: 4  Lock_time: 0  Rows_sent: 3  Rows_examined: 1294
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 4182969 group by rating;"

Query_time: 3  Lock_time: 0  Rows_sent: 3  Rows_examined: 446
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 630148 group by rating;"

Query_time: 5  Lock_time: 0  Rows_sent: 3  Rows_examined: 3788
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 1835698 group by rating;"

Query_time: 17  Lock_time: 0  Rows_sent: 3  Rows_examined: 4311
"select rating, count(*) as tally from user_match_ratings where rated_user_id = 1269322 group by rating;"

মাইএসকিউএল সংস্করণ:

  • প্রোটোকল সংস্করণ: 10
  • সংস্করণ: 5.0.77-লগ
  • সংস্করণ বিডিবি: স্লিপাইক্যাট সফ্টওয়্যার: বার্কলে ডিবি 4.1.24: (জানুয়ারী 29, ২০০৯)
  • সংস্করণ সংকলন মেশিন: x86_64 version_compile_os: redhat-linux-gnu

সারণী তথ্য:

SHOW COLUMNS FROM user_match_ratings;

দেয়:

╔═══════════════╦════════════╦════╦═════╦════════╦════════════════╗
║ id            ║ int(11)    ║ NO ║ PRI ║ NULL   ║ auto_increment ║
║ rater_user_id ║ int(11)    ║ NO ║ MUL ║ NULL   ║                ║
║ rated_user_id ║ int(11)    ║ NO ║ MUL ║ NULL   ║                ║
║ rating        ║ varchar(1) ║ NO ║     ║ NULL   ║                ║
║ created_at    ║ datetime   ║ NO ║     ║ NULL   ║                ║
╚═══════════════╩════════════╩════╩═════╩════════╩════════════════╝

নমুনা ক্যোয়ারী:

select * from mutual_match_ratings where id=221673540;

দেয়:

╔═══════════╦═══════════════╦═══════════════╦════════╦══════════════════════╗
║ id        ║ rater_user_id ║ rated_user_id ║ rating ║ created_at           ║
╠═══════════╬═══════════════╬═══════════════╬════════╬══════════════════════╣
║ 221673540 ║ 5699713       ║ 3890950       ║ N      ║ 2013-04-09 13:00:38  ║
╚═══════════╩═══════════════╩═══════════════╩════════╩══════════════════════╝

ইনডেক্সে

সারণীতে 3 টি সূচক সেট আপ করা হয়েছে:

  1. একক সূচক চালু rated_user_id
  2. সংমিশ্রিত সূচক rater_user_idএবংcreated_at
  3. সংমিশ্রিত সূচক rated_user_idএবংrater_user_id
ব্যবহারকারীর_ম্যাচ_রেটিংগুলি থেকে সূচি প্রদর্শন করুন;

দেয়:

╔════════════════════╦════════════╦═══════════════════════════╦══════════════╦═══════════════╦═══════════╦═════════════╦══════════╦════════╦═════════════════════════╦════════════╦══════════════════╗
║ Table              ║ Non_unique ║ Key_name                  ║ Seq_in_index ║ Column_name   ║ Collation ║ Cardinality ║ Sub_part ║ Packed ║ Null                    ║ Index_type ║ Comment          ║
╠════════════════════╬════════════╬═══════════════════════════╬══════════════╬═══════════════╬═══════════╬═════════════╬══════════╬════════╬═════════════════════════╬════════════╬══════════════════╣
║ user_match_ratings ║ 0          ║ PRIMARY                   ║ 1            ║ id            ║ A         ║ 220781193   ║ NULL     ║ NULL   ║ BTREE                   ║            ║                  ║
║ user_match_ratings ║ 1          ║ user_match_ratings_index1 ║ 1            ║ rater_user_id ║ A         ║ 11039059    ║ NULL     ║ NULL   ║ BTREE                   ║            ║                  ║
║ user_match_ratings ║ 1          ║ user_match_ratings_index1 ║ 2            ║ created_at    ║ A         ║ 220781193   ║ NULL     ║ NULL   ║ BTREE                   ║            ║                  ║
║ user_match_ratings ║ 1          ║ user_match_ratings_index2 ║ 1            ║ rated_user_id ║ A         ║ 4014203     ║ NULL     ║ NULL   ║ BTREE                   ║            ║                  ║
║ user_match_ratings ║ 1          ║ user_match_ratings_index2 ║ 2            ║ rater_user_id ║ A         ║ 220781193   ║ NULL     ║ NULL   ║ BTREE                   ║            ║                  ║
║ user_match_ratings ║ 1          ║ user_match_ratings_index3 ║ 1            ║ rated_user_id ║ A         ║ 2480687     ║ NULL     ║ NULL   ║ BTREE                   ║            ║                  ║
╚════════════════════╩════════════╩═══════════════════════════╩══════════════╩═══════════════╩═══════════╩═════════════╩══════════╩════════╩═════════════════════════╩════════════╩══════════════════╝

এমনকি সূচিগুলির সাথেও এই প্রশ্নগুলি ধীর।

আমার প্রশ্ন:

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

বর্তমানে আমাদের 16 গিগাবাইট মেমরি রয়েছে; তবে আমরা হয় বিদ্যমান মেশিনটিকে 32 গিগাবাইটে আপগ্রেড করতে চাইছি বা একটি নতুন মেশিনকে কমপক্ষে এতটা দিয়ে যুক্ত করব, সম্ভবত শক্ত রাষ্ট্রের ড্রাইভগুলিও।


1
আপনার প্রশ্ন অবিশ্বাস্য। আমি আপনার বর্তমান সমাধানটির জন্য খুব আগ্রহী যে আপনি কীভাবে <= 2 সেকেন্ডে ফলাফল পেতে পেরেছিলেন? কারণ আমার কাছে একটি টেবিল রয়েছে যার মধ্যে কেবল 20 মিলিয়ন রেকর্ড রয়েছে এবং এখনও এটি 30 সেকেন্ডের জন্য লাগে SELECT QUERY। আপনি দয়া করে পরামর্শ দিন? পিএস আপনার প্রশ্ন আমাকে এই সম্প্রদায়ে যোগদান করতে বাধ্য করেছে (y);)
— নালপয়েন্টার

2
আপনি যে টেবিলটিতে জিজ্ঞাসা করছেন সেগুলি সূচকগুলি দেখুন .. প্রায়শই উপযুক্ত সূচক তৈরি করে প্রশ্নের মধ্যে অনেকগুলি উন্নতি করা যেতে পারে। সর্বদা নয় তবে এমন অনেকগুলি উদাহরণ দেখা যায় যেখানে কোয়েরিতে কলামের বিপরীতে যেখানে শর্টকাটগুলির বিরুদ্ধে একটি সূচক সরবরাহ করে কোয়েরিগুলি দ্রুত করা হয়। বিশেষত যদি একটি টেবিল আরও বড় এবং বড় হয়।
— র্যাঙ্কনুডল

অবশ্যই @ র্যাঙ্কনুডল ধন্যবাদ. আমি যথাক্রমে চেক করব।
— নালপয়েন্টার

উত্তর:


28

ইস্যুতে চিন্তাভাবনা, এলোমেলো ক্রমে নিক্ষিপ্ত:

  • এই জিজ্ঞাসার জন্য সুস্পষ্ট সূচক হল: (rated_user_id, rating)। এমন কোয়েরি যা মিলিয়ন ব্যবহারকারীদের মধ্যে কেবল একটির জন্য ডেটা পেয়েছে এবং 17 সেকেন্ডের দরকার রয়েছে তা কিছু ভুল করছে: (rated_user_id, rater_user_id)সূচীটি থেকে পড়া এবং তারপরে ratingকলামটির জন্য (শত থেকে হাজার) মান সারণী থেকে পড়া , ratingকোনও সূচীতে নেই। সুতরাং, ক্যোরিয়াকে টেবিলের অনেকগুলি সারি পড়তে হবে যা বিভিন্ন ডিস্কের অবস্থানগুলিতে অবস্থিত।

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

  • মাইএসকিউএল, 5.1, 5.5 বা এমনকি 5.6 (এমনকি: পারকোনা এবং মারিয়াডিবি সংস্করণগুলি) এর আরও নতুন সংস্করণে চলে যাওয়ার কথা বিবেচনা করুন bu বাগগুলি সংশোধন করা হয়েছে, অপ্টিমাইজার উন্নত হয়েছে এবং আপনি ধীর অনুসন্ধানের জন্য নিম্ন প্রান্তিকিকে 1 সেকেন্ডের চেয়ে কম স্থির করতে পারেন (10 মিলিসেকেন্ডের মতো)। এটি আপনাকে ধীর অনুসন্ধানগুলি সম্পর্কে আরও ভাল তথ্য দেবে।

  • এর ডেটাটাইপের জন্য পছন্দটি ratingঅদ্ভুত। VARCHAR(1)? কেন হবে না CHAR(1)? কেন হবে না TINYINT? এটি আপনাকে কিছুটা জায়গা সাশ্রয় করবে, টেবিলের টিন এবং সূচীতে যেটিতে (কলাম) অন্তর্ভুক্ত থাকবে। বর্ণ (1) কলামে চরের (1) ওপরে আরও একটি বাইট প্রয়োজন এবং সেগুলি utf8 হয়, তবে (var) চর কলামগুলিতে 1 (টিনিনেন্ট) এর পরিবর্তে 3 (বা 4) বাইটের প্রয়োজন হবে।


2
আপনি যদি ভুল ডেটাটাইপ ব্যবহার করেন তবে% এর পরিপ্রেক্ষিতে পারফরম্যান্সের কতগুলি প্রভাব বা স্টোরেজ অপচয়?
— ফ্লাইংআটম

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

-1

আমি মাঝে মাঝে 60 মিলিয়ন রেকর্ড সহ জার্মান সরকারের পক্ষে সারণীগুলি পরিচালনা করি।

আমাদের এই টেবিলগুলি প্রচুর ছিল।

এবং আমাদের একটি টেবিল থেকে মোট সারিতে বহুবার জানতে হবে।

ওরাকল এবং মাইক্রোসফ্ট প্রোগ্রামারদের সাথে কথা বলার পরে আমরা এত খুশি হইনি ...

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

আমরা অন্য সমস্ত উপায়ে চেষ্টা করেছি। এটি এখন পর্যন্ত সবচেয়ে দ্রুতগতিতে।

আমরা এখন 1998 সাল থেকে এইভাবে ব্যবহার করি এবং আমাদের বহু মিলিয়ন রেকর্ড টেবিলগুলিতে কখনও কোনও সারিগুলির কোনও ভুল সংখ্যা ছিল না।


7
আমি গত 18 বছরে চালু হওয়া কয়েকটি বৈশিষ্ট্য সন্ধান করার পরামর্শ দেব suggest অন্যদের মধ্যে count(*)কিছু উন্নতি হয়েছে।
— dezso

আপনি কীভাবে জানবেন যে আপনি কখনই কোনও ভুল নম্বর পান নি যদি আপনি সেগুলি গণনা করতে না পারেন? uhmmmm ...
— Tonca

-3

আমি রেটিংয়ের ধরণগুলিতে ভাগ করার চেষ্টা করব, যেমন:

মিউচুয়াল_ম্যাচ_রেটিং_এন, মিউচুয়াল_ম্যাচ_রেটিংস_স, ইত্যাদি

আপনার প্রতিটি প্রকারের জন্য একটি কোয়েরি করা উচিত, তবে সম্ভবত এটি অন্য উপায়ে দ্রুত faster একবার চেষ্টা করে দেখো.

এটি ধরে নিয়েছে যে আপনার কাছে রেটিং ধরণের একটি নির্দিষ্ট সংখ্যা রয়েছে এবং এই নতুন কাঠামোর সাথে খারাপ হতে পারে এমন অন্যান্য প্রশ্নের জন্য আপনার এই টেবিলটির দরকার নেই।

যদি এটি হয় তবে স্থান এবং রক্ষণাবেক্ষণের ক্ষেত্রে (বা অ্যাপ্লিকেশন যুক্তি) যদি সাশ্রয়ী হয় তবে আপনার অন্য পদ্ধতির সন্ধান করা উচিত বা টেবিলের দুটি কপি (আপনার প্রাথমিক টেবিল এবং বিভাজনযুক্ত) বজায় রাখা উচিত।

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