it-swarm.com.de

Nicht gut geschriebene Skripte verursachen einen hohen Ressourcenverbrauch

Kürzlich hat der Administrator eines Servers einen Bericht über eine Joomla-Site gesendet, die zu viel Ressourcenverbrauch verursacht. Der Bericht sagte:

URSACHE DES HOHEN RESSOURCENVERBRAUCHS:

Wir haben eine detaillierte Untersuchung durchgeführt und es stellte sich heraus, dass Joomla langsame Abfragen in Bezug auf seine Datenbank ausführt, wodurch der Server schließlich überlastet wird. Der Server versucht, Ihre langsamen Abfragen auszuführen, während andere Prozesse in die Warteschlange gestellt werden, bis Speicher freigegeben wird. Während sie jedoch warten, stapeln sie sich und verursachen weitere Probleme. Es kann viele Gründe für langsame Datenbankabfragen geben, aber die folgenden drei sind die häufigsten:

  1. Große Datenbank
  2. Nicht gut geschriebene Skripte
  3. Große Anzahl interner Links, die die Datenbank direkt abfragen.

Im Folgenden sind einige der Datenbankabfragen aufgeführt, die langsam sind und viele Serverressourcen beanspruchen:

  1. Vor 1 Std. 8 Min. 56 Sek. Für 87.512348 Sek. In der Datenbank ausgeführt -> sporthis_tory Datum: 2015-08-24 22:24:22 Abfragezeit: 87.512348 Überprüfte Zeilen: 5593: Gesendete Zeilen 247 Sperrzeit: 0.000197 SELECT a.id, CASE WHEN CHAR_LENGTH (a.alias ) THEN CONCAT_WS (':', a.id, a.alias) ELSE a.id END as slug, CASE WHEN CHAR_LENGTH (cc.alias) THEN CONCAT_WS (':', cc.id, cc.alias) ELSE cc. id END as catslug FROM g06j5_content AS a LEFT JOIN g06j5_categories AS cc ON cc.id = a.catid WHERE a.catid = 105 AND a.state = 1 AND a.access = 1 AND (a.state = 1 OR a.state = -1) AND (publish_up = '0000-00-00 00:00:00' OR publish_up = '2015-08-25 03:22 : 36 ') ORDER BY a.created DESC; --------------------------------------- ----------------------------------------> --------- --------------
  2. Vor 57m 7s für 67.095903 Sek. In der Datenbank ausgeführt -> sporthis_tory Datum: 2015-08-24 22:36:11 Query_time: 67.095903 Rows_examined: 5593: Rows_sent 247 Lock_time: 0.000252 SELECT a.id, CASE WHEN CHAR_LENGTH (a.alias) THEN CONCAT_WS (':', a.id, a.alias) ELSE a.id END als Slug, CASE WHEN CHAR_LENGTH (cc.alias) THEN CONCAT_WS (':', cc.id, cc.alias) ELSE cc.id END as catslug FROM g06j5_content AS a LEFT JOIN g06j5_categories AS cc ON cc.id = a.catid WHERE a.catid = 105 AND a.state = 1 AND a.access = 1 AND (a.state = 1 OR a.state = -1) AND (publish_up = '0000-00-00 00:00:00' OR publish_up = '2015-08-25 03:35: 01 ') ORDER BY a.created DESC; ---------------------------------------- ---------------------------------------> ---------- -------------
  3. Vor 1 Std. 8 Min. 56 Sek. Für 52.137859 Sek. In der Datenbank ausgeführt -> sporthis_tory Datum: 2015-08-24 22:24:22 Abfragezeit: 52.137859 Überprüfte Zeilen: 5593: Gesendete Zeilen 247 Sperrzeit: 0.000169 SELECT a.id, CASE WHEN CHAR_LENGTH (a.alias ) THEN CONCAT_WS (':', a.id, a.alias) ELSE a.id END as slug, CASE WHEN CHAR_LENGTH (cc.alias) THEN CONCAT_WS (':', cc.id, cc.alias) ELSE cc. id END as catslug FROM g06j5_content AS a LEFT JOIN g06j5_categories AS cc ON cc.id = a.catid WHERE a.catid = 105 AND a.state = 1 AND a.access = 1 AND (a.state = 1 OR a.state = -1) AND (publish_up = '0000-00-00 00:00:00' OR publish_up = '2015-08-25 03:22 : 52 ') ORDER BY a.created DESC; --------------------------------------- ----------------------------------------> --------- --------------
  4. Vor 1 Std. 3 Min. 29 Sek. Für 45.861259 Sek. In der Datenbank ausgeführt -> sporthis_tory Datum: 2015-08-24 22:29:49 Abfragezeit: 45.861259 Überprüfte Zeilen: 5593: Gesendete Zeilen 247 Sperrzeit: 0.000650 SELECT a.id, CASE WHEN CHAR_LENGTH (a.alias ) THEN CONCAT_WS (':', a.id, a.alias) ELSE a.id END als Slug, CASE WHEN CHAR_LENGTH (cc.alias) THEN CONCAT_WS (':', cc.id, cc.alias) ELSE cc. id END as catslug FROM g06j5_content AS a LEFT JOIN g06j5_categories AS cc ON cc.id = a.catid WHERE a.catid = 105 AND a.state = 1 AND a.access = 1 AND (a.state = 1 OR a.state = -1) AND (publish_up = '0000-00-00 00:00:00' OR publish_up = '2015-08-25 03:28 : 40 ') ORDER BY a.created DESC; --------------------------------------- ----------------------------------------> --------- --------------
  5. Vor 1h 20m 37s für 40.682781 Sek. In der Datenbank ausgeführt -> sporthis_tory Datum: 2015-08-24 22:12:41 Abfragezeit: 40.682781 Überprüfte Zeilen: 1320: Gesendete Zeilen 440 Sperrzeit: 0.000176 SELECT a.id, CASE WHEN CHAR_LENGTH (a.alias ) THEN CONCAT_WS (':', a.id, a.alias) ELSE a.id END as slug, CASE WHEN CHAR_LENGTH (cc.alias) THEN CONCAT_WS (':', cc.id, cc.alias) ELSE cc. id END as catslug FROM g06j5_content AS a LEFT JOIN g06j5_categories AS cc ON cc.id = a.catid WHERE a.catid = 111 AND a.state = 1 AND a.access = 1 AND (a.state = 1 OR a.state = -1) AND (publish_up = '0000-00-00 00:00:00' OR publish_up = '2015-08-25 03:11 : 50 ') BESTELLEN BEI a.created DESC;

sporthis_tory 175,1 MB

Aus den obigen Abfragen können wir schließen, dass Ihr Problem durch nicht gut geschriebene Skripte verursacht wird.

Ich möchte wissen, wie man mit dem Debuggen von so etwas beginnt (die Skripte finden, die die Abfrage ausführen, die Datenbank optimieren), oder es ist nur die Site, die wächst und wir müssen einen größeren Plan kaufen?

Aktualisieren:

Vielen Dank für die nützlichen Informationen. Ich möchte hinzufügen, dass die Site aufgrund des Ressourcenverbrauchs nicht verfügbar ist. Daher kann ich mich erst anmelden, wenn ich das Problem behoben habe. Ich habe EXPLAIN mit der Abfrage erweitert ausgeführt und dieses Ergebnis erhalten>>

id: 1
select_type: SIMPLE
Tabelle: a
Typ: index_merge
mögliche_Tasten: idx_access, idx_state, idx_catid
Schlüssel: idx_catid, idx_state, idx_access
Key_len: 4,1,4
ref: NULL
Zeilen: 1275
gefiltert: 75.06
Extra: Verwenden von intersect (idx_catid, idx_state, idx_access); Verwenden von where; Filesort verwenden

id: 1
select_type: SIMPLE
Tabelle: cc
Typ: const
mögliche_Tasten: PRIMARY
Schlüssel: PRIMARY
Key_len: 4
ref: const
Zeilen: 1
gefiltert: 100,00
Extra:

Ich habe keine Erfahrung mit der Indizierung von Datenbanken und möchte dieses Problem beheben. Muss ich einen neuen Index mit allen drei Spalten (idx_catid, idx_state, idx_access) erstellen oder sind sie bereits indiziert? Ich vermute auch, dass diese Abfrage von einem Joomla-Modul stammt. Kann ich auf irgendeine Weise feststellen, welches Modul diese seltsamen Abfragen ausführt? Beachten Sie, dass ich nicht der Ersteller der Website bin. Ich wurde gerade gebeten, dieses Problem zu lösen.

2

Obwohl Sie eine Menge Maßnahmen ergreifen können, um dies zu beheben, sollte meine Hauptempfehlung hoffentlich ziemlich schnell sein.

Zunächst wird jedoch erläutert, wie diese Probleme behoben werden können. Da sie Ihnen die langsamen Abfragen geben, sollten Sie zunächst feststellen, warum sie langsam sind! Die Datenbank wird Ihnen dies bis zu einem gewissen Grad mitteilen. Melden Sie sich daher bei Ihrer Datenbank an (entweder über die Befehlszeile oder so ähnlich wie PhpMyAdmin). Führen Sie eine der langsamen Abfragen mit dem Wort EXPLAIN am Anfang aus:

EXPLAIN SELECT a.id, CASE WHEN CHAR_LENGTH (a.alias) THEN CONCAT_WS (':', a.id, a.alias) ELSE a.id END as slug, CASE WHEN CHAR_LENGTH (cc.alias) THEN CONCAT_WS (': ', cc.id, cc.alias) ELSE cc.id END as catslug FROM g06j5_content AS LEFT JOIN g06j5_categories AS cc ON cc.id = a.catid WHERE a.catid = 105 AND a.state = 1 AND a.access = 1 AND (a.state = 1 OR a.state = -1) AND (publish_up = '0000-00-00 00:00:00' OR publish_up = '2015-08-25 03:22:36 ') ORDER BY a.created DESC;

Dies sollte Ihnen eine Datentabelle geben, aus der hervorgeht, wie Ihre Datenbank diese Informationen abrufen wird. Dinge, die ich hier erwarten würde (ohne die Erklärung tatsächlich ausgeführt zu haben ...):

  • Der Join befindet sich auf der ID für #__categories, sodass die zusätzliche Tabelle mit einem Schlüssel geladen werden sollte
  • Außerdem sollte angegeben werden, mit welchem ​​Schlüssel (falls vorhanden) Datensätze aus der Tabelle #__content geladen werden. Joomla wird standardmäßig mit einem Index für catid, state und access ausgeliefert, die alle in Ihrer WHERE -Klausel enthalten sind und daher verwendet werden könnten

Normalerweise empfehle ich für die Optimierung, den zu verwendenden Index herauszufinden und dann der Tabelle einen besseren Index hinzuzufügen, um diese Art von Abfrage zu unterstützen. (Und denken Sie daran, dass der Kompromiss mit Indizes immer eine schnellere Lesezeit für eine langsamere Schreibzeit ist. Wenn Sie also viele Indizes hinzufügen, sollten Sie in der Lage sein, Datensätze schneller auszuwählen, aber neue Datensätze langsamer hinzuzufügen.)

Wenn Sie sich alles ansehen, was Sie auswählen, möchten Sie eine bestimmte catid, einen bestimmten Status und einen bestimmten Zugriff. Wenn Sie also einen Index hinzufügen, der alle drei dieser Spalten in einer enthält, kann die Datenbank die richtigen Zeilen noch schneller auswählen. Es wird noch einige DB-Prozesse geben, da diese nach created sortiert werden müssen, um sie zu ordnen.

Um Ihre Entscheidung tatsächlich zu treffen, empfehle ich, die Datenbank für Ihre Website lokal zu kopieren, der Tabelle g06j5_content verschiedene Indizes hinzuzufügen und diese EXPLAIN-Abfrage so lange auszuführen, bis die Abfrage in erster Linie von Indizes ausgeführt wird.


Eine zusätzliche Anmerkung, Sie können in Ihren Abfragen sehen, dass Sie sowohl eine Prüfung auf a.state = 1 Als auch auf (a.state = 1 OR a.state = -1) Durchführen. Dies ist offensichtlich eine nutzlose Überprüfung, da state für denselben Datensatz nicht 1 und -1 sein kann, was bedeutet, dass es überhaupt nutzlos ist, (a.state = 1 OR a.state = -1) Darin zu haben.

Ich empfehle nicht, so etwas aufzuspüren und zu entfernen, da die Datenbank über ein Abfrageoptimierungsprogramm verfügt, das die zweite Prüfung entfernt (da es keinen Wert hinzufügt).

Wenn Sie die Abfrage tatsächlich ändern möchten, möchte ich herausfinden, warum Sie genau zwei publish_up-Zeiten auswählen: (publish_up = '0000-00-00 00:00:00' OR publish_up = '2015-08-25 03:11:50').

Es gibt keinen Index für publish_up-Zeiten. Dies bedeutet im Allgemeinen, dass die Datenbank jeden Datensatz durchsuchen muss, um festzustellen, ob dies zutrifft oder nicht. Ich bin nicht sicher, wie die Unterstreichungslogik bei der Auswahl nach einer bestimmten Publish_Up-Zeit aussieht, da dies so selten der Fall sein wird.

2
David Fritsch

Sie können den Debug-Modus in den Joomla-Einstellungen aktivieren. Dadurch wird eine hübsche Liste aller Abfragen am Ende jeder Seite mit vielen Debuginformationen gedruckt. In dieser Liste erfahren Sie auch, wie lange eine Abfrage gedauert hat und welche Indizes sie verwendet.

Außerdem haben Sie 5593 Artikel in Ihrer Datenbank, was ein Grund dafür sein könnte, dass es so lange gedauert hat. Vielleicht helfen die Standardindizes bei so vielen Artikeln nicht weiter.

2
Harald Leithner