Archiv der Kategorie: Datenbank

Problem beim Post erstellen bei >300.000 Posteinträgen – Eltern-Dropdown (Page Parent) entfernen

WordPress und hohe Postanzahl

WordPress kommt gut mit Instanzen zurecht, die mehr als 300.000 Beiträge, Seiten oder andere Custom Post Type Einträge aufweisen.

Obwohl sich in der Datenbank aufgrund von Autosaves und Revisionen ein Vielfaches von 300.000 Einträgen befindet, sind Seiten im Front- und Backend noch geschmeidig bedienbar.

Das trifft auch auf Sharedhosting wie Uberspace zu, was viele im Vorhinein nicht vermuten würden.

Problemzone Elternseiten-Dropdown

So ganz uneingeschränkt stimmt das nicht.
Ein riesiges Problem ist das Elterndropdown im Backend:

Eltern- oder Pageparent Dropdown
Eltern- oder Pageparent Dropdown

In diesem Dropdown werden alle Seiten aufgelistet, die es so gibt.
Das heißt, dass ALLE Seiten/CPT aus der Datenbank geholt werden. Das ist schon mal ein Performanceproblem, da das eine ressourcenfressende Abfrage ist.

Das nächste Problem besteht darin, alle Seiten dann in HTML umzusetzen. Es kommt also für jeden Eintrag ein weiteres Objekt in dem Dropdown hinzu.

Bei zb vier Einträgen wie hier ist das kein Problem:

Dropdown-Einträge im HTML-Quelltext
Dropdown-Einträge im HTML-Quelltext

Müssen aber zb 300.000 Einträge erstellt werden, wird das schnell zum Flaschenhals am Webserver.

Also:

Der Webserver wird dadurch extremst ausgelastet und es kann zu einem Ausreizen des Arbeitsspeichers oder der Exec-Time kommen.

Was dann passiert, sollte klar sein, oder?

Wir bekommen eine (meist) weiße Seite mit einem Server-Error.

Das liegt sicher nicht in unserem Interesse.

Lösung: Dropdown beseitigen, zb

Einerseits könnte man aus dem Dropdown ein Autovervollständigenfeld machen, wie das zb bei der Tag-Auswahl bekannt ist.

Wenn man aber die Auswahl der Elternseite sowieso nicht braucht, kann man diesen Bereich gleich ganz entfernen.

Bei selbst erstellen Post Types reicht es, wenn ‚page-attributes‘ bei ’supports‘ weggelassen wird:

Register Post Type Beispiel
Register Post Type Beispiel

Dadurch erhält der Post-Type im Backend auf der Bearbeitenseite gar kein Dropdown, um ein Elternelement auszuwählen.

Wenn ich einem bestehenden Post-Type, wie zb „page“, das Dropdown wegnehmen möchte, brauche ich die Funktion remove_post_type_support():

Das war’s auch schon!

Links

https://codex.wordpress.org/Function_Reference/remove_post_type_support

https://codex.wordpress.org/Function_Reference/register_post_type

Neue Tabellen-Spalte per Code mit wpdb oder dbDelta hinzufügen

Grundsätzlich bietet WordPress als Basis für Webapps ja eine einfache Möglichkeit, um Daten in die von WP mitgebrachten Tabellen einzugeben.

Siehe:

https://www.wp-entwickler.at/was-ist-dbdelta-und-wofuer-brauch-ich-das/
https://www.wp-entwickler.at/was-ist-dbdelta-und-wofuer-brauch-ich-das/

https://www.wp-entwickler.at/ueberpruefen-ob-tabelle-tabellenspalte-oder-tabellenzeile-existiert-mit-wpdb/
https://www.wp-entwickler.at/ueberpruefen-ob-tabelle-tabellenspalte-oder-tabellenzeile-existiert-mit-wpdb/

Eigene Tabellen sind in vielen Fällen aber besser.
Will ich nun zu einer Tabelle eine neue Spalte per PHP-Code hinzufügen, gibt es mehrere Möglichkeiten:

 

ALTER TABLE

$wpdb->query( "ALTER TABLE {$table_name} ADD {$column_name} LONGTEXT" );

Die einfachste und durchschaubarste Lösung ist wahrscheinlich ALTER TABLE.
Hier erstelle ich in einer Tabelle, notiert mit {$table_name}, eine Spalte mit dem Type LONGTEXT, notiert mit {$column_name}.

dbDelta

DbDelta ist eigentlich dafür da, um Tabellen in der Datenbank zu erstellen. Siehe auch den vorherigen Blogeintrag zu dbDelta.

Man kann dbDelta aber auch dazu verwenden, um Spalten anzufügen.

Aber nur um Spalten hinzuzufügen – dbDelta löscht keine Spalten. Daher funktionieren folgende Beispiele gleich, ohne Fehler zu werfen. Für euch getestet.

 

		
$sql =
	"CREATE TABLE {$table_name} (
          ID mediumint(9) NOT NULL AUTO_INCREMENT,
          post_ID mediumint(9) NOT NULL,
          term_ID mediumint(9) NOT NULL,
          {$column_name} LONGTEXT,
          PRIMARY KEY  (id)
        ) ENGINE = InnoDB {$charset_collate};";

dbDelta( $sql );

 

$sql =
	"CREATE TABLE {$table_name} (
          {$column_name} LONGTEXT,
        ) ENGINE = InnoDB {$charset_collate};";

dbDelta( $sql );

 

In beiden Fällen füge ich der Tabelle {$table_name} die Spalte {$column_name} hinzu.
Im ersten Fall verwende ich den gleichen Code wie zum erzeugen der Tabelle.
Im zweiten Fall Fall fehlen die meisten Zeilen aus dem ersten Beispiel. Dennoch funktioniert beides gleich.

Kleiner Hinweis: Will ich dbDelta verwenden, muss ich die wp-admin/includes/upgrade.php Datei einbinden:

require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );

 

https://developer.wordpress.org/reference/functions/dbdelta/
https://developer.wordpress.org/reference/functions/dbdelta/

http://wordpress.stackexchange.com/questions/78667/dbdelta-alter-table-syntax
http://wordpress.stackexchange.com/questions/78667/dbdelta-alter-table-syntax

https://codex.wordpress.org/Creating_Tables_with_Plugins#Adding_an_Upgrade_Function
https://codex.wordpress.org/Creating_Tables_with_Plugins#Adding_an_Upgrade_Function

 

http://stackoverflow.com/questions/21330932/add-new-column-to-wordpress-database/21331762#21331762
http://stackoverflow.com/questions/21330932/add-new-column-to-wordpress-database/21331762#21331762

Überprüfen ob Tabelle, Tabellenspalte oder Tabellenzeile existiert mit WPDB

WordPress bietet viele und einfache Möglichkeiten, um Daten zu speichern, ohne eigenen SQL-Code schreiben zu müssen.

Custom Fields (oder Post Metas) werden oft für allerhand Daten verwendet.
Man muss sich nicht selbst um Userinterfaces oder Update- und Löschmechanismen kümmern.

Doch die Tabellenstruktur von WordPress reicht oft nicht, oder ergibt bei größeren Projekten keinen Sinn.

Wenn es dann darum geht, kurze Checks und Überprüfungen an eigenen Tabellen durchzuführen, gehen mir die WordPress eigenen Mittel aus.

Daher nachfolgend ein paar Snippets als Hilfestellung:

Überprüfen ob Tabelle existiert

$table_exists = $wpdb->get_var( "SHOW TABLES LIKE '{$table_name}'" );

Das ist eine recht einfache Übung – {$table_name} ist dabei der Tabellennamen, auf den man überprüfen möchte.

Überprüfen ob Zeile existiert

$wpdb->get_row( "SELECT * FROM {$table_name} WHERE post_ID = {$post_id}" );
$wpdb->get_row( "SELECT post_ID FROM {$table_name} WHERE post_ID = {$post_id}" );

Dazu gibt es mehrere Möglichkeiten – siehe die Doku zu wpdb.
Hier wird aus einer Tabelle, hier dargestellt mit {$table_name}, eine Zeile mit einer bestimmen post_ID geholt.
Im ersten Fall werden alle Datenfelder der Zeile geholt. Für das Überprüfen ob eine Zeile vorhanden ist, könnte das zu viel an Information und Speicherbelegung sein.
Es reicht vollkommen, wenn ich mir nur ein Datenfeld oder eine Spalte aus der Zeile hole.

Überprüfen ob Spalte existiert

$columns = $wpdb->get_results(
"DESC {$table_name}"
);

{$table_name} ist wieder der Tabellenname.
DESC ist shorthand für DESCRIPTION. Mit obigem Befehl hole ich mir alle Informationen zu einer speziellen Tabelle. Ich bekomme nicht nur die Spaltennamen sondern eine Fülle an Infos..
In dem obigen Fall kommt ein Objekt an Arrays zurück. Jedes Array stellt eine Spalte dar. Ich kann diese Arrays mit einer Schleife durchlaufen, oder zb. auch das Objekt serialisieren und nach Text (= die spezielle Spalte) durchsuchen.

 

Dort wo es nötig ist, bitte nicht auf das Absichern der Abfragen vergessen. WordPress bietet dazu eine Hilfestellung mit $wpdb->prepare an.
Hineiws: Dabei handelt es sich nicht um prepared statements auf DB-Ebene sondern um WordPress-Funktionalität.

 

https://codex.wordpress.org/Class_Reference/wpdb
https://codex.wordpress.org/Class_Reference/wpdb

Was ist dbDelta() und wofür brauch ich das?

dbDelta() ist so eine WordPress-Funktion, die einem immer ein bisserl Kopfzerbrechen bereitet aber extremst hilfreich ist.

Worum geht’s bei dbDelta()?

Die Developer-Seite sagt:

Modifies the database based on specified SQL statements.

Also:
Ändert die Datenbank aufgrund von angegebenen SQL-Anweisungen.
Die Funktion ist sehr hilfreich wenn’s darum geht, eine neue, eigene Tabelle anzulegen. Wenn mir die WP eigene Tabellenstruktur nicht ausreicht und ich mit WP-Bordmitteln (Funktionen) also eine Tabelle erzeugen will.

Doch nicht nur erzeugen ist möglich, auch das Abändern.

Genau da wird’s praktisch! Ich kann meine eigenen Tabellen ohne großen Aufwand, ohne große Überlegungen ändern.
Also Spalten einfügen, Datentypen anpassen o.ä.
Was dbDelta() in dem Zusammenhang nicht kann, ist löschen.

Die Probleme?

Man muss sehr genau sein, was die Anweisungen für dbDelta() betrifft.
Genau heißt in dem Fall, dass es sogar auf ein Leerzeichen zu viel ankommt oder auf die komplette Großschreibung einzelner Wörter.
Die genaue Liste der einzelnen Problemfelder von dbDelta() ist bei folgenden Links ersichtlich:

https://codex.wordpress.org/Creating_Tables_with_Plugins#Creating_or_Updating_the_Table
https://codex.wordpress.org/Creating_Tables_with_Plugins#Creating_or_Updating_the_Table

 

http://wordpress.stackexchange.com/questions/78667/dbdelta-alter-table-syntax/78670#78670
http://wordpress.stackexchange.com/questions/78667/dbdelta-alter-table-syntax/78670#78670

Hilfe in Sicht?

Ja! Es tut sich natürlich immer irgendwo etwas im WordPres-Universum.

Dominik Schilling, ein Core-Entwickler hat Verbesserungen angekündigt, die zb. die oben angesprochenen Probleme beheben.

 

https://twitter.com/ocean90/status/753244345629827072
https://twitter.com/ocean90/status/753244345629827072

https://make.wordpress.org/core/2016/07/13/dbdelta-updates-in-4-6/

dbDelta() updates in 4.6


https://make.wordpress.org/core/2016/07/13/dbdelta-updates-in-4-6/

 

Wer sich für die noch offenen Baustellen interessiert wird hier fündig:

https://core.trac.wordpress.org/query?status=!closed&summary=~dbDelta
https://core.trac.wordpress.org/query?status=!closed&summary=~dbDelta

 

https://developer.wordpress.org/reference/functions/dbdelta/
https://developer.wordpress.org/reference/functions/dbdelta/

https://codex.wordpress.org/Creating_Tables_with_Plugins
https://codex.wordpress.org/Creating_Tables_with_Plugins