[RUBY] [Rails] Eine Sammlung von Tipps, die sofort zur Verbesserung der Leistung hilfreich sind

Einführung

Hier sind einige Tipps, mit denen Sie Ihre Leistung in Rails verbessern können. Wir haben eine große Auswahl an Artikeln, von gebrauchsfertigen bis hin zu Verbesserungen, deren Verbesserung einige Zeit in Anspruch nimmt.

Wir hoffen, dass dies dazu beiträgt, die Leistung der in der Entwicklung befindlichen App zu verbessern.

[Tipps 1] Verbessere N + 1

Wenn N + 1 trotzdem auftritt, versuchen Sie es zu beseitigen. In den meisten Fällen sollte dies der Leistungsengpass für Ihre App sein.

books_controller.rb


class BooksController < ApplicationController
  def index
    @book = Book.all
  end
end

erb:index.html.erb


<% @book.each do |book|
  <%= book.title %>
  <%= book.user.name %> #Hier N.+1 passiert
<% end %>     

Im obigen Codebeispiel tritt N + 1 auf, wenn der dem Buch zugeordnete Benutzer gelesen wird.

Schreiben wir den Controller wie folgt um.

books_controller.rb


class BooksController < ApplicationController
  def index
    @book = Book.includes(:user)
  end
end

Wenn alle Modelle in model.all erfasst wurden, besteht eine hohe Wahrscheinlichkeit, dass N + 1 auftritt, und häufig wird nicht alles verwendet. Es wird auch empfohlen, die Edelsteinkugel in der App zu installieren, um N + 1 zu erkennen.

https://github.com/flyerhzm/bullet

Im obigen Beispiel wird auch "Includes" verwendet, aber es wäre schön, "Preload" und "eifriges Laden" richtig verwenden zu können.

Unterschiede zwischen ActiveRecord-Joins, Preloads, Includes und eifrigem Laden

[Tipps 2] Verwenden Sie Größe anstelle von Zählung

Wenn Sie count verwenden, geben Sie SQL aus. Wenn Sie daher die Anzahl der Modelle überprüfen möchten, verwenden Sie stattdessen "Größe".

Es ist ein Fall, der normalerweise unerwartet auftritt, aber es ist einfach, weil Sie einfach "count" durch "size" ersetzen.

** Bei Verwendung von count **


user = User.all
user.count
#Eine SELECT-Anweisung mit der Zählfunktion wird ausgegeben
   (4.6ms)  SELECT COUNT(*) FROM `users`
=> 100

** Bei Verwendung von Größe **

user = User.all
user.size
#SQL-Abfrage wird nicht ausgegeben
=> 100

[Tipps 3] Keine Verwendung vorhanden?

Wie count , exist? Gibt SQL aus, wenn es für ein Modellobjekt verwendet wird. Wenn Sie überprüfen möchten, ob es vorhanden ist, verwenden Sie stattdessen "vorhanden".

*** Bei Verwendung von exit? ***


user = User.where(deleted: true)
user.exist?
#SQL wird ausgegeben
  User Load (5.4ms)  SELECT `users`.* FROM `users` WHERE `users`.`deleted` = TRUE
=> []

*** Bei Verwendung von Geschenk? ***

user = User.where(deleted: true)
user.present?
#SQL wird nicht ausgegeben
=> []

[Tipps 4] Drehen Sie nicht das Ergebnis, das alle mit jedem erzielt haben

Es ist ein Muster, wie alle Benutzer mit "alle" zu bekommen und es mit jedem zu drehen. Es ist ein Muster, das in der Stapelverarbeitung üblich ist.

User.all.each do |user|
  #Code, der etwas mit dem Objekt des Benutzers tut
end

Wie ich in den N + 1-Tipps erwähnt habe, verdächtigen Sie den Code, sobald alles in den Prozess eingeht.

Bei der obigen Implementierung wird nach dem Erweitern aller Benutzerfälle auf den Speicher jeder Prozess von jedem ausgeführt, sodass der Speicherverbrauch hoch wird.

Verwenden Sie find_each anstelle von all.

User.find_each do |user|
  #Code, der etwas mit dem Objekt des Benutzers tut
end

find_each ruft jeweils 1000 Datensätze ab und verarbeitet die abgerufenen Datensätze nacheinander.

Nach dem Erwerb von 1000 Gegenständen werden die nächsten 1000 Gegenstände erneut erworben und so weiter.

Wenn Sie die Anzahl der Datensatzerweiterungen angeben möchten, verwenden Sie übrigens die Schwestermethode find_in_batches. Sie können die Anzahl der Datensätze im Argument der Methode angeben.

[Tipps 5] Generieren unnötiger Active Record-Objekte

Obwohl nicht so viel wie das N + 1-Problem und jedes oben erwähnte Muster, ist dies auch eine Implementierung, die in der Regel durchgeführt wird, wenn Sie nicht vorsichtig sind.

user_names = User.all.map(&:name)

Der oben beschriebene kartenbasierte Ansatz erzeugt unnötige Active Record-Objekte und ist nicht sehr performant.

Da Active Record-Objekte eine große Anzahl von Modulen und Methoden umfassen, ist es teuer, sie selbst zu generieren und Speicher zu verbrauchen.

Wenn es eine Möglichkeit gibt, kein Active Record-Objekt zu erstellen, denken Sie darüber nach.

user_names = User.pluck(:name)

Durch Zupfen konnten wir unnötige Objekterstellung vermeiden.

[Tipps 6] Erwägen Sie die Einführung von Cache und asynchroner Verarbeitung

Sie können auch einen Cache verwenden oder den Prozess asynchron machen, wenn sich die Leistung verschlechtert.

** Cache verwenden ** Erwägen Sie die Einführung von Redis usw. Es ist möglicherweise eine gute Idee, Stammdaten zu lesen. Wenn Sie den Einführungsort jedoch nicht sorgfältig prüfen, kann dies zu Fehlern führen.

** Asynchrone Verarbeitung machen ** Schwere Verarbeitung wird asynchron mit "Sidekiq" und "verzögertem Job" von Gem. Ich sehe oft, wie man den Mail-Sendeprozess asynchron macht.

Am Ende

Wie war das. Bisher haben wir Tipps eingeführt, mit denen sich die Leistung leicht verbessern lässt, wenn Sie beim Codieren mit Rails darauf achten.

Wenn es andere Möglichkeiten gibt oder wenn hier etwas nicht stimmt, lass es mich bitte im Kommentarbereich wissen lol

Recommended Posts

[Rails] Eine Sammlung von Tipps, die sofort zur Verbesserung der Leistung hilfreich sind
Eine Sammlung von Eclipse-Verknüpfungen, die neue Absolventen nützlich finden
Es ist gerade erst, aber eine Sammlung von Befehlen, die häufig in Rails angezeigt werden
Eine Sammlung einfacher Fragen für Java-Anfänger
RSpec-Sammlung, die ich häufig verwendet habe
Grundkenntnisse der Informatik und ihrer Praxis, die Sie zur Leistungssteigerung kennen sollten
Generieren Sie eine eindeutige Auflistung von Werten aus einer Auflistung, die doppelte Werte enthält
Erklärung von Ruby on Rails für Anfänger ③ ~ Erstellen einer Datenbank ~
Ein Durchbruch, dass Sie nicht gut im Selbststudium sind und sich sofort auf andere verlassen (für sich selbst)
Gradle TIPS-Sammlung (für mich)