কম্পিউটার

ActiveRecord পারফরম্যান্সের সমস্যা সমাধান করা

ActiveRecord হল রুবি অন রেলের সবচেয়ে জাদুকরী বৈশিষ্ট্য। আমাদের সাধারণত এর অভ্যন্তরীণ কার্যকারিতা নিয়ে চিন্তা করার দরকার নেই, তবে আমরা যখন করি, তখন এখানে কীভাবে অ্যাপসিগন্যাল হুডের নীচে কী ঘটছে তা জানতে আমাদের সাহায্য করতে পারে৷

ActiveRecord কি?

ActiveRecord সম্পর্কে কথা বলতে, আমাদের প্রথমে ফ্রেমওয়ার্কের কথা ভাবতে হবে, বিশেষ করে MVC ফ্রেমওয়ার্ক সম্পর্কে। MVC মানে মডেল-ভিউ-কন্ট্রোলার, এবং এটি গ্রাফিকাল এবং ওয়েব অ্যাপ্লিকেশনের জন্য একটি জনপ্রিয় সফ্টওয়্যার ডিজাইন প্যাটার্ন।

MVC ফ্রেমওয়ার্কগুলি গঠিত:

  • মডেল৷ :ব্যবসায়িক যুক্তি এবং ডেটা অধ্যবসায় পরিচালনা করে।
  • দেখুন৷ :প্রেজেন্টেশন লেয়ার চালায় এবং ইউজার ইন্টারফেস আঁকে।
  • নিয়ন্ত্রক :সবকিছু একসাথে বাঁধে।

ActiveRecord হল মডেল রুবি ইন রেল ফ্রেমওয়ার্কের উপাদান। এটি কোড এবং ডেটার মধ্যে একটি বিমূর্তকরণ স্তর প্রবর্তন করে, তাই আমাদের নিজেদেরকে এসকিউএল কোড লিখতে হবে না। প্রতিটি মডেলকে একটি টেবিলে ম্যাপ করা হয় এবং CRUD ক্রিয়াকলাপ সম্পাদন করার জন্য বিভিন্ন পদ্ধতি প্রদান করে (তৈরি করুন, পড়ুন, আপডেট করুন এবং মুছুন)।

AppSignal দিয়ে ActiveRecord মনিটরিং

বিমূর্ততাগুলি যাদুকর বলে মনে হয় - তারা আমাদের সেই বিবরণগুলি উপেক্ষা করতে সহায়তা করে যা আমাদের জানার প্রয়োজন নেই এবং হাতে থাকা টাস্কটিতে ফোকাস করা দরকার। কিন্তু যখন জিনিসগুলি প্রত্যাশিত হিসাবে কাজ করে না, তখন তারা যে জটিলতা যোগ করে তা মূল কারণ নির্ধারণ করা কঠিন করে তুলতে পারে। AppSignal আমাদেরকে রেলে আসলে কী ঘটছে তার একটি বিশদ বিবরণ দিতে পারে।

প্রতিক্রিয়া সময় গ্রাফ

চলুন প্রথম সমস্যাটি দেখে নেওয়া যাক। পারফরম্যান্সের সমস্যাগুলি সমাধান করা একটি পুনরাবৃত্তিমূলক প্রক্রিয়া। AppSignal-এ আপনার Rails অ্যাপ্লিকেশন রিপোর্ট করার পরে, ঘটনা-এ যান৷> পারফরম্যান্স .

রেসপন্স টাইম গ্রাফ প্রতিটি নেমস্পেসের জন্য রেসপন্স টাইম পার্সেন্টাইল দেখাবে। অ্যাক্টিভরেকর্ড ইভেন্টগুলি স্বয়ংক্রিয়ভাবে নেমস্পেসে বরাদ্দ করা হয় যে অনুরোধ বা ব্যাকগ্রাউন্ড জবের মধ্যে প্রশ্নগুলি চালানো হয়৷

এর পরে, ইভেন্ট গ্রুপ গ্রাফটি দেখুন। এটি ক্যাটাগরি অনুসারে কতটা সময় ব্যয় করে তা দেখায়। active_record দ্বারা কত আপেক্ষিক সময় ব্যয় হয় তা পরীক্ষা করুন . আপনার সমস্ত নামস্থানে ব্যবহার পরীক্ষা করুন৷

গ্রাফটি অবিলম্বে আমাদের বলবে যে আমাদের কোড-অপ্টিমাইজ করার প্রচেষ্টাকে কোথায় ফোকাস করা উচিত।

আপনি যখন পারফরম্যান্স গ্রাফ ড্যাশবোর্ডে থাকবেন, তখন আপনার অ্যাপ্লিকেশনে স্বাভাবিকের চেয়ে বেশি কোনো কার্যকলাপ নেই তা নিশ্চিত করতে প্রতিক্রিয়ার সময় এবং থ্রুপুট পরীক্ষা করুন৷

স্লো কোয়েরি ড্যাশবোর্ড

এখন যেহেতু আমরা চিহ্নিত করেছি যে সমস্যাটি ডেটা-বাউন্ড, আসুন দেখি আমরা মূল কারণ নির্ধারণ করতে জুম ইন করতে পারি কিনা৷

উন্নতি খুলুন ধীরগতির প্রশ্নগুলি৷ ড্যাশবোর্ড এই পৃষ্ঠাটি সামগ্রিক সময়ের উপর প্রভাব দ্বারা র‌্যাঙ্ক করা SQL প্রশ্নের তালিকা দেখায়। সমস্ত ActiveRecord থেকে উদ্ভূত প্রশ্নগুলি একটি sql.active_record হিসাবে দেখানো হয়েছে ঘটনা।

এটির বিশদ বিবরণ দেখতে শীর্ষস্থানীয় কোয়েরিতে ক্লিক করার চেষ্টা করুন৷ ড্যাশবোর্ড গড় সময়কাল এবং ক্যোয়ারী পাঠ্য দেখায়।

নীচে স্ক্রোল করা আপনাকে গত কয়েক ঘন্টার প্রশ্নের উত্তরের সময় এবং উদ্ভূত ক্রিয়া দেখাবে৷

আপনি হয়তো খুঁজে পেতে পারেন যে কিছু কর্মের সাথে সম্পর্কিত ঘটনা আছে। এর মানে হল যে অ্যাপসিগন্যাল ক্যোয়ারী চলাকালীন একটি পারফরম্যান্স ইভেন্ট তৈরি করেছে, কিন্তু এর মানে এই নয় যে ActiveRecord এর কারণ।

পারফরম্যান্স পরিমাপ ড্যাশবোর্ড

যখন AppSignal একটি নতুন এন্ডপয়েন্ট বা ব্যাকগ্রাউন্ড জব রেকর্ড করে তখন কর্মক্ষমতা পরিমাপের ঘটনাগুলি খোলা হয়৷

ঘটনাগুলি পারফরমেন্স-এ অবস্থিত৷> ইস্যু তালিকা ড্যাশবোর্ড।

ঘটনার পৃষ্ঠাটি MVC উপাদানগুলির প্রতিটির জন্য অতিবাহিত সময় এবং বরাদ্দের সংখ্যা দেখায়৷ ActiveRecord সমস্যাগুলি active_record-এ দীর্ঘ সময়কাল প্রদর্শন করবে বিভাগ।

ইভেন্টের টাইমলাইন দেখায় কিভাবে ইভেন্টটি সময়ের সাথে এগিয়েছে।

ActiveRecord সমস্যা খোঁজা

এই বিভাগে, আমরা দেখব কিভাবে AppSignal আমাদের কিছু সাধারণ ActiveError সমস্যা সনাক্ত করতে সাহায্য করতে পারে।

প্রাসঙ্গিক কলাম নির্বাচন করা

ডেটাবেস জ্ঞান বলে যে আমাদের সর্বদা কাজের জন্য প্রয়োজনীয় কলামগুলি পুনরুদ্ধার করা উচিত। উদাহরণস্বরূপ, পরিবর্তে SELECT * FROM people আমাদের উচিত SELECT first_name, surname, birthdate FROM people . এটি সবই ভাল এবং ভাল, কিন্তু আমরা কীভাবে এটি রেলে করব?

ডিফল্টরূপে, ActiveRecord সমস্ত কলাম পুনরুদ্ধার করে।

Person.all.each {
      # process data
}

ভাগ্যক্রমে, আমাদের কাছে select আছে প্রয়োজনীয় কলাম বাছাই করার পদ্ধতি:

Person.select(:name, :address, :birthdate).each {
      # process data
}

এটা মনে হতে পারে যে আমি সামান্য বিশদ সম্পর্কে আবেশী আছি। কিন্তু প্রশস্ত টেবিলে, সমস্ত কলাম নির্বাচন করা শুধুই অপচয়। আপনি লক্ষ্য করবেন যে এটি ঘটলে, ActiveRecord মেমরির বড় অংশ বরাদ্দ করে:

N+1 সমস্যা

N+1 সমস্যাটি ঘটে যখন অ্যাপ্লিকেশনটি ডাটাবেস থেকে রেকর্ডের একটি সেট পায় এবং এটির মাধ্যমে লুপ করে। এটি অ্যাপ্লিকেশানটিকে N+1 ক্যোয়ারী চালায়, যেখানে N হল প্রাথমিকভাবে প্রাপ্ত সারিগুলির সংখ্যা। আপনি যেমন কল্পনা করতে পারেন, টেবিল বাড়ার সাথে সাথে এই প্যাটার্নটি খারাপভাবে স্কেল করে। এটি এমন একটি ক্ষতিকারক সমস্যা যে AppSignal আপনাকে এটি সম্পর্কে বিশেষভাবে সতর্ক করে:

N+1 সমস্যা সাধারণত সংশ্লিষ্ট মডেলের সাথে দেখা যায়। কল্পনা করুন আমাদের একটি ব্যক্তি মডেল আছে:

class Person < ApplicationRecord
    has_many :addresses
end

প্রতিটি ব্যক্তির অনেক ঠিকানা থাকতে পারে:

class Address < ApplicationRecord
    belongs_to :person
end

ডেটা পুনরুদ্ধার করার সবচেয়ে সহজ উপায় N+1 সমস্যার দিকে নিয়ে যায়:

class RelatedTablesController < ApplicationController
    def index
        Person.all.each do |person|
            person.addresses.each do |address|
            address.address
            end
        end
    end
end

আপনি AppSignal-এ দেখতে পাচ্ছেন যে অ্যাপ্লিকেশনটি একটি SELECT চলছে৷ জন প্রতি:

এই বিশেষ ক্ষেত্রের সমাধান সহজ:ব্যবহার অন্তর্ভুক্ত, যা ActiveRecord কে প্রয়োজনীয় কলামগুলির জন্য ক্যোয়ারী অপ্টিমাইজ করতে বলে:

class RelatedTablesController < ApplicationController
    def index
        Person.all.includes(:addresses).each do |person|
            person.addresses.each do |address|
            address.address
            end
        end
    end
end

এখন আমাদের কাছে N+1 এর পরিবর্তে দুটি প্রশ্ন আছে:

Processing by RelatedTablesController#index as HTML
   (0.2ms)  SELECT sqlite_version(*)
  ↳ app/controllers/related_tables_controller.rb:12:in `index'
  Person Load (334.6ms)  SELECT "people".* FROM "people"
  ↳ app/controllers/related_tables_controller.rb:12:in `index'

  Address Load (144.4ms)  SELECT "addresses".* FROM "addresses" WHERE "addresses"."person_id" IN (1, 2, 3, . . .)

সারণী প্রতি সর্বনিম্ন প্রয়োজনীয় প্রশ্নগুলি সম্পাদন করুন

এটি কখনও কখনও N+1 সমস্যার সাথে বিভ্রান্ত হয়, তবে এটি একটু ভিন্ন। যখন আমরা একটি টেবিলের অনুসন্ধান করি, তখন আমাদের সমস্ত ডেটা পুনরুদ্ধার করা উচিত যা আমরা মনে করি আমাদের পঠিত ক্রিয়াকলাপগুলিকে ন্যূনতম করতে হবে। যাইহোক, প্রচুর নির্দোষ-সুদর্শন কোড রয়েছে যা অপ্রয়োজনীয় প্রশ্নগুলিকে ট্রিগার করে। উদাহরণস্বরূপ, দেখুন কিভাবে count সর্বদা একটি SELECT COUNT(*) এর ফলাফল হয় নিম্নলিখিত দৃশ্যে প্রশ্ন:

<ul>
    <% @people.each do |person| %>
        <li><%= person.name %></li>
    <% end %>
</ul>
 
<h2>Number of Persons: <%= @people.count %></h2>

এখন ActiveRecord দুটি প্রশ্ন করে:

Rendering duplicated_table_query/index.html.erb within layouts/application
  (69.1ms)  SELECT COUNT(*) FROM "people" WHERE "people"."name" = ?  [["name", "John Waters"]]
↳ app/views/duplicated_table_query/index.html.erb:3
Person Load (14.6ms)  SELECT "people".* FROM "people" WHERE "people"."name" = ?  [["name", "John Waters"]]
↳ app/views/duplicated_table_query/index.html.erb:6

AppSignal-এ, আপনি যে লক্ষণটি লক্ষ্য করবেন তা হল দুটি active_record আছে একই টেবিলে ইভেন্ট:

বাস্তবতা হল আমাদের দুটি প্রশ্নের প্রয়োজন নেই; আমাদের মেমরিতে আমাদের প্রয়োজনীয় সমস্ত ডেটা ইতিমধ্যেই রয়েছে। এই ক্ষেত্রে, সমাধান হল count অদলবদল করা size সহ :

<ul>
<% @people.each do |person| %>
<li><%= person.name %></li>
<% end %>
</ul>
 
<h2>Number of Persons: <%= @people.size %></h2>

এখন আমাদের একটি একক SELECT আছে , যেমন হওয়া উচিত:

Rendering duplicated_table_query/index.html.erb within layouts/application
Person Load (63.2ms)  SELECT "people".* FROM "people" WHERE "people"."name" = ?  [["name", "Abdul Strosin"]]
↳ app/views/duplicated_table_query/index.html.erb:5

আরেকটি সমাধান হল মেমরিতে ডেটা ক্যাশে করার জন্য প্রিলোড ব্যবহার করা।

রেলের মধ্যে সমষ্টিগত ডেটা কম্পিউটিং

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

যখনই আমরা max এর মতো রুবি ফাংশনগুলি অবলম্বন করি তখনই আমরা রেলগুলিতে একত্রীকরণ করি , min , অথবা sum ActiveRecord উপাদান বা অন্যান্য গণনার উপরে।

class AggregatedColumnsController < ApplicationController
    def index
        @mean = Number.pluck(:number).sum()
    end
end

সৌভাগ্যবশত, ActiveRecord মডেলগুলি নির্দিষ্ট পদ্ধতিগুলিকে অন্তর্ভুক্ত করে যা ডাটাবেসের একত্রীকরণ ফাংশনগুলির সাথে মানচিত্র তৈরি করে। উদাহরণস্বরূপ, নিম্নলিখিত ক্যোয়ারী মানচিত্র SELECT SUM(number) FROM ... , যা আগের উদাহরণের তুলনায় অনেক দ্রুত এবং সস্তা চালানো হয়:

# controller
 
class AggregatedColumnsController < ApplicationController
    def index
        @mean = Number.sum(:number)
    end
end
Processing by AggregatedColumnsController#index as */*
  (2.4ms)  SELECT SUM("numbers"."number") FROM "numbers"

আপনার যদি আরও জটিল বা সম্মিলিত একত্রীকরণ ফাংশনের প্রয়োজন হয়, তাহলে আপনাকে কিছুটা কাঁচা SQL কোড অন্তর্ভুক্ত করতে হতে পারে:

sql = "SELECT AVG(number), STDDEV(number), VAR(number) FROM ..."
@results = ActiveRecord::Base.connection.execute(sql)

বড় লেনদেন পরিচালনা করা

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

আমরা ActiveRecord::Base.transaction এর মাধ্যমে একটি একক লেনদেনে পরিবর্তনের একটি ব্যাচ বান্ডিল করতে পারি .

class BigTransactionController < ApplicationController
    def index
        ActiveRecord::Base.transaction do
            (1..1000).each do
                Person.create(name: 'Les Claypool')
            end
        end
    end
end

বড় লেনদেন ব্যবহার করার জন্য অনেক বৈধ কেস আছে। এগুলি অবশ্য ডাটাবেসকে ধীর করে দেওয়ার ঝুঁকির মধ্যে পড়ে৷ এছাড়াও, নির্দিষ্ট থ্রেশহোল্ড অতিক্রম করা লেনদেনের ফলে ডাটাবেস তাদের প্রত্যাখ্যান করবে।

লেনদেন অনেক বড় হওয়ার প্রথম লক্ষণ হল commit transaction এ অনেক সময় ব্যয় করা ঘটনা:

ডাটাবেসের কনফিগারেশন সমস্যাগুলি বাদ দিয়ে, সমাধান হল লেনদেনকে ছোট ছোট অংশে বিভক্ত করা৷

ডাটাবেস মনিটরিং

কখনও কখনও যদিও আমরা কোড অনুসন্ধান করি, আমরা এটিতে কিছু ভুল খুঁজে পাই না। তারপর, ডাটাবেস নিজেই একটি সমস্যা হতে পারে. ডাটাবেস ইঞ্জিনগুলি জটিল, এবং অনেক কিছু ভুল হতে পারে:কম মেমরি, ডিফল্ট সেটিংস, অনুপস্থিত সূচক, অসুবিধাজনকভাবে নির্ধারিত ব্যাকআপ কাজ। আমরা ডাটাবেস চালিত মেশিন সম্পর্কে তথ্য না পাওয়া পর্যন্ত ছবিটি সম্পূর্ণ হতে পারে না।

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

নিম্নলিখিত লক্ষণগুলি দেখাতে পারে যে ডাটাবেসের সাথে কিছু চলছে। পরিদর্শন এ যান৷> হোস্ট মেট্রিক্স আপনার সার্ভারে সম্পদের ব্যবহার দেখতে ড্যাশবোর্ড:

  • উচ্চ মেমরি ব্যবহার :সঠিকভাবে চালানোর জন্য ডাটাবেসের অনেক মেমরির প্রয়োজন — অন্যান্য সিস্টেমের চেয়ে বেশি। ডেটাসেট বাড়ার সাথে সাথে মেমরির প্রয়োজনীয়তাগুলি সাধারণত স্কেল করে। আমাদের হয় আরও মেমরি যোগ করতে হবে বা সময়ে সময়ে বিভিন্ন মেশিনের মধ্যে ডেটাসেট বিভক্ত করতে হবে।
  • অদলবদল ব্যবহার :আদর্শভাবে, ডাটাবেস মেশিনের অদলবদল মেমরির প্রয়োজন হবে না। অদলবদল ডাটাবেস কর্মক্ষমতা হত্যা. এর উপস্থিতি মানে আরও গভীর কনফিগারেশন বা মেমরির সমস্যা।
  • উচ্চ I/O ব্যবহার :ডিস্ক ক্রিয়াকলাপের শিখরগুলি রক্ষণাবেক্ষণের কাজগুলির কারণে হতে পারে যেমন ডাটাবেস পুনঃসূচীকরণ বা ব্যাক আপ করা। পিক আওয়ারে এই কাজগুলি করা অবশ্যই পারফরম্যান্সকে প্রভাবিত করবে৷

👋 আপনি যদি এই নিবন্ধটি পছন্দ করেন তবে রুবি (রেলগুলিতে) পারফরম্যান্স সম্পর্কে আমরা আরও অনেক কিছু লিখেছি, আমাদের রুবি পারফরম্যান্স মনিটরিং চেকলিস্টটি দেখুন৷

উপসংহার

কর্মক্ষমতা সমস্যা নির্ণয় করা একটি সহজ কাজ নয়. আজ, আমরা শিখেছি কিভাবে অ্যাপসিগন্যাল ব্যবহার করে সমস্যার উৎস দ্রুত চিহ্নিত করতে হয়।

আসুন AppSignal এবং Ruby on Rails সম্পর্কে শিখতে থাকি:

  • ActiveRecord পারফরম্যান্স:N+1 কোয়েরি অ্যান্টিপ্যাটার্ন
  • রেলস দ্রুত:আপনার ভিউ পারফরম্যান্স অপ্টিমাইজ করুন
  • রেল প্যাটার্ন এবং অ্যান্টি-প্যাটার্নে রুবির ভূমিকা

পি.এস. আপনি যদি রুবি ম্যাজিক পোস্টগুলি প্রেস থেকে বের হওয়ার সাথে সাথে পড়তে চান তবে আমাদের রুবি ম্যাজিক নিউজলেটারে সাবস্ক্রাইব করুন এবং একটি পোস্টও মিস করবেন না!


  1. কিভাবে OpenStruct পারফরম্যান্সকে মেরে ফেলতে পারে

  2. ডাটাবেস কর্মক্ষমতা টিউনিং

  3. Redis কর্মক্ষমতা উপর চিন্তা

  4. Windows 11 এর গতি বাড়ানোর 12 উপায়