আমি এমন একটি প্রকল্পে কাজ করছি ( রেলস 3.0.15, রুবি 1.9.3-পি 125-পারফ ) যেখানে ডিবি লোকালহোস্টে রয়েছে এবং ব্যবহারকারীদের সারণীতে 100K এর চেয়ে কিছু বেশি রেকর্ড রয়েছে ।
ব্যবহার
RAND দ্বারা আদেশ ()
বেশ ধীর
User.order ( "এন ডি (ID)")। প্রথম
হয়ে
নির্বাচন করুন users
* users
র্যান্ডের অর্ডার থেকে (আইডি) সীমাবদ্ধ 1
এবং প্রতিক্রিয়া নিতে 8 থেকে 12 সেকেন্ড সময় নেয় !!
রেল লগ:
ব্যবহারকারী লোড (11030.8ms) নির্বাচন করুন users
* users
র্যান্ডের মাধ্যমে অর্ডার থেকে () সীমাবদ্ধ 1
mysql এর ব্যাখ্যা থেকে
+----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+
| 1 | SIMPLE | users | ALL | NULL | NULL | NULL | NULL | 110165 | Using temporary; Using filesort |
+----+-------------+-------+------+---------------+------+---------+------+--------+---------------------------------+
আপনি দেখতে পাচ্ছেন যে কোনও সূচক ব্যবহার করা হয়নি ( সম্ভাব্য_কিজ = এনএলএল ), একটি অস্থায়ী সারণী তৈরি করা হয় এবং পছন্দসই মানটি পেতে অতিরিক্ত পাসের প্রয়োজন হয় ( অতিরিক্ত = অস্থায়ী ব্যবহার করে; ফাইলসোর্ট ব্যবহার করে )।
অন্যদিকে, ক্যোয়ারিকে দুটি অংশে বিভক্ত করে এবং রুবি ব্যবহার করে, প্রতিক্রিয়ার সময়টিতে আমাদের যুক্তিসঙ্গত উন্নতি হবে।
users = User.scoped.select(:id);nil
User.find( users.first( Random.rand( users.length )).last )
(; কনসোল ব্যবহারের জন্য নিল)
রেল লগ:
ব্যবহারকারী লোড (25.2ms) থেকে আইডি নির্বাচন users
ব্যবহারকারী লোড (0.2ms) নির্বাচন করুন
users
। * থেকে users
কোথায় users
। id
= 106854 সীমাবদ্ধ 1
এবং মাইএসকিএল এর ব্যাখ্যা কেন প্রমাণ করে:
+----+-------------+-------+-------+---------------+--------------------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+--------------------------+---------+------+--------+-------------+
| 1 | SIMPLE | users | index | NULL | index_users_on_user_type | 2 | NULL | 110165 | Using index |
+----+-------------+-------+-------+---------------+--------------------------+---------+------+--------+-------------+
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | users | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+-------+
আমরা এখন কেবলমাত্র সূচি এবং প্রাথমিক কী ব্যবহার করতে পারি এবং প্রায় 500 গুণ দ্রুত কাজটি করতে পারি!
হালনাগাদ:
মন্তব্যগুলিতে আইক্যান্টবেকুল দ্বারা নির্দেশিত হিসাবে সারণীতে রেকর্ড মুছে ফেলা থাকলে উপরের সমাধানটির একটি ত্রুটি রয়েছে।
যে একটি workaround হতে পারে
users_count = User.count
User.scoped.limit(1).offset(rand(users_count)).first
যা দুটি প্রশ্নের অনুবাদ করে
SELECT COUNT(*) FROM `users`
SELECT `users`.* FROM `users` LIMIT 1 OFFSET 148794
এবং প্রায় 500ms এ চলে।