Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

Backend: Performance Dropdown Include-Elemente #8696

Open
klauswagner opened this issue Apr 10, 2017 · 12 comments
Open

Backend: Performance Dropdown Include-Elemente #8696

klauswagner opened this issue Apr 10, 2017 · 12 comments
Labels

Comments

@klauswagner
Copy link

klauswagner commented Apr 10, 2017

Ich habe ein recht großes System mit 14 Sprachseitenbäumen und insgesamt 23.844 Inhaltselementen am laufen. Performance-Technisch ist alles top, AUßER:
Das Dropdown "Bezogenes Inhaltselement" (Elementtyp "Inhaltselement" der Kategorie "Include-Elemente") lädt natürlich ewig an den 23844 Options. So lange, dass u.a. der Chrome erstmal hängen bleibt, dann eine Meldung anzeigt "Seite reagiert nicht" und nach langem Warten (ca. 30 - 40 Sekunden) dann endlich das Dropdown nutzbar anzeigt.
Da das so im besten Fall nur gelegentlich nutzbar ist habe ich als Workaround die Include-Elemente über die Datenbank angepasst. Dem Kunden kann ich das aber nicht zutrauen.

Spontane Ideen:

  • Options des Dropdowns nur laden wenn mehr wie vier Zeichen (z.B. "ID 1") in das Suchfeld eingegeben werden (und evtl. Anzahl der Resultate limitieren -> Festlegbar in den Einstellungen)
  • Vorgeschaltenes Dropdown mit einer Seitenbaum-Auswahl. Das Dropdown "Bezogenes Inhaltselement" lädt/durchsucht nur Inhaltselemente dieses Seitenbaums. (Bringt bei sehr großen einsprachigen Seiten natürlich nichts).

Edit:
Contao-Version: 3.5.21

@aschempp
Copy link
Member

aschempp commented Apr 10, 2017 via email

@Samson1964
Copy link

Da ich nie die ganz alten Elemente benötige, habe ich den options_callback überschrieben und lade nur die Elemente der letzten 30 Tage. Damit fahre ich seit über einem Jahr sehr gut und es wird nur ein Bruchteil der knapp 29.000 Inhaltselemente angeboten.
zz_modul/dca/tl_content.php:

<?php

$GLOBALS['TL_DCA']['tl_content']['fields']['cteAlias']['options_callback'] = array('tl_mycontent', 'getAlias');

class tl_mycontent extends Backend
{

	/**
	 * Import the back end user object
	 */
	public function __construct()
	{
		parent::__construct();
		$this->import('BackendUser', 'User');
	} 

	/**
	 * Get all content elements and return them as array (content element alias)
	 *
	 * @return array
	 */
	public function getAlias()
	{
		$arrPids = array();
		$arrAlias = array();
		$alter = time() - 86400 * 30; // Nur Inhaltselemente der letzten 30 Tage anzeigen
		
		if (!$this->User->isAdmin)
		{
			foreach ($this->User->pagemounts as $id)
			{
				$arrPids[] = $id;
				$arrPids = array_merge($arrPids, $this->Database->getChildRecords($id, 'tl_page'));
			}

			if (empty($arrPids))
			{
				return $arrAlias;
			}

			$objAlias = $this->Database->prepare("SELECT c.id, c.pid, c.type, (CASE c.type WHEN 'module' THEN m.name WHEN 'form' THEN f.title WHEN 'table' THEN c.summary ELSE c.headline END) AS headline, c.text, a.title FROM tl_content c LEFT JOIN tl_article a ON a.id=c.pid LEFT JOIN tl_module m ON m.id=c.module LEFT JOIN tl_form f on f.id=c.form WHERE a.pid IN(". implode(',', array_map('intval', array_unique($arrPids))) .") AND (c.ptable='tl_article' OR c.ptable='') AND c.id!=? AND c.tstamp >= ? ORDER BY a.title, c.sorting")
									   ->execute(Input::get('id'), $alter);
		}
		else
		{
			$objAlias = $this->Database->prepare("SELECT c.id, c.pid, c.type, (CASE c.type WHEN 'module' THEN m.name WHEN 'form' THEN f.title WHEN 'table' THEN c.summary ELSE c.headline END) AS headline, c.text, a.title FROM tl_content c LEFT JOIN tl_article a ON a.id=c.pid LEFT JOIN tl_module m ON m.id=c.module LEFT JOIN tl_form f on f.id=c.form WHERE (c.ptable='tl_article' OR c.ptable='') AND c.id!=? AND c.tstamp >= ? ORDER BY a.title, c.sorting")
									   ->execute(Input::get('id'), $alter);
		}

		while ($objAlias->next())
		{
			$arrHeadline = deserialize($objAlias->headline, true);

			if (isset($arrHeadline['value']))
			{
				$headline = StringUtil::substr($arrHeadline['value'], 32);
			}
			else
			{
				$headline = StringUtil::substr(preg_replace('/[\n\r\t]+/', ' ', $arrHeadline[0]), 32);
			}

			$text = StringUtil::substr(strip_tags(preg_replace('/[\n\r\t]+/', ' ', $objAlias->text)), 32);
			$strText = $GLOBALS['TL_LANG']['CTE'][$objAlias->type][0] . ' (';

			if ($headline != '')
			{
				$strText .= $headline . ', ';
			}
			elseif ($text != '')
			{
				$strText .= $text . ', ';
			}

			$key = $objAlias->title . ' (ID ' . $objAlias->pid . ')';
			$arrAlias[$key][$objAlias->id] = $strText . 'ID ' . $objAlias->id . ')';
		}

		return $arrAlias;
	}
	
} 

@backbone87
Copy link
Contributor

backbone87 commented Apr 11, 2017

Würde es so wie @aschempp machen: mit hilfe eines dafür gedachten widgets, wie mein https://github.com/hofff/contao-selectri oder andreas' tablelookupwizard

Auch die funktion von @Samson1964 ist gut

Alle diese funktionen werden übrigens von meiner https://github.com/hofff/contao-content (nachfolger meiner backboneit_mod_article) mit hilfe eines neuen content-elements/moduls namens "Inhaltsreferenzen" umgesetzt. Mit dieser lassen sich in einem CE/Module beliebig viele einzelne Module, einzelne Artikel oder alle Artikel in einem oder mehrerer beliebiger Layoutbereiche einer Seite referenzieren. Einziger haken: die referenzierung von CEs ist noch nicht umgesetzt, da wir aufgrund schlechter erfahrungen keine CE-referenzen beim pflegen von inhalten verwenden. Hinweis: Wenn du bereits meine mod_article erweiterung in dem system einsetzt, dann werden die CEs/Module der mod_article erweiterung konvertiert. Das sehe ich als etwas experimental an, deswegen bitte DB backup oder vorher die mod_article entfernen.

@madmaharaja
Copy link

Das ist interessant. Ich habe nämlich in einer Installation über 25.000 Inhaltselemente (über 100 Seitenbäume) und das Dropdown "Bezogenes Inhaltselement" ist ohne Ladeverzögerung prompt da mit der gesamten Auswahlliste.

@klauswagner
Copy link
Author

@madmaharaja Das ist wirklich interessant. Auf was für einem Server betreibst du das? Was für eine Datenbank verwendest du? Welche Contao-Version setzt du ein? Läuft das Contao ohne Modifikationen am Backend?

@madmaharaja
Copy link

@wagnerwagner Ist noch die Version 3.1.5. -- frag nicht, warum ich noch nicht upgedated habe -- ist eine lange Geschichte :-)
Ist ein Managed Server bei Domain Factory, läuft mit einer MySQL-Datenbank.
Ich bin mir nicht sicher, was du mit Modifikationen am Backend meinst. Wir haben jedenfalls einige Erweiterungen (eigene und "reguläre") laufen.

@klauswagner
Copy link
Author

@madmaharaja Ein Managed Server bei DF hat ne recht gute Performance. Sehr wahrscheinlich ist dieser wirklich so performant dass das Dropdown prompt ausgegeben wird.
Die von mir beschriebene Problematik bezieht sich auf eine Contao-Installation die auf einem All-Inkl Premium-WEBHOSTING läuft. Dort teilen sich leider bis zu 50 Kunden einen Server. Der Managed-Server kostet aber auch 90 Euro / Monat mehr als das Webhosting.

Das Thema lässt sich natürlich durch höhere Leistung recht gut in den Griff bekommen. Aber vielleicht lässt sich die entsprechende Funktion noch weiter optimieren/verbessern (z.B. mit einer Konfigurationsmöglichkeit für dieses Dropdown), damit größere Contao-Systeme auch auf weniger leistungsstarken Servern/Hosting-Paketen besser laufen.

@madmaharaja
Copy link

@wagnerwagner Optimierung ist natürlich immer gut! :-)
Ich hab jetzt mal in einer Test-Installation (3.5.27) von mir nachgesehen, die auf einem Shared-Hosting-Server liegt. Dort habe ich jetzt mal wild Seitenbäume dupliziert, sodass anschließend fast 27.000 Inhaltselemente vorlagen. Es hat dann auch über 20 Sekunden gedauert, bis das Dropdown der bezogenen Inhaltselemente gerendert war. Ich finde deine Lösungsvorschläge jedenfalls gut.

@Samson1964
Copy link

@madmaharaja: Wir sind auch bei df) mit einem ManagedServer, aber auf meine 29.000 Inhaltselemente wartete ich 20-30 Sekunden. FF meldet dann immer "ein Skript antwortet nicht" oder Ähnliches. Und während der Eingabe der ID gab es auch ständig Verzögerungen.
Deshalb habe ich mir den Workaround mit nur den Elementen der letzten x Tage einfallen lassen. Damit fahre ich bis jetzt sehr gut. Ältere Elemente habe ich noch nie gebraucht.

@Aybee
Copy link
Contributor

Aybee commented Jun 14, 2017

Das liegt evtl. gar nicht am Server. 29.000 CEs sind ca 2,5MB an HTML-Code nur für das Select. Versuche mal sone Seite als statische lokale Seite aufzurufen. Könnte sein, dass der Browser damit auch Probleme hat. Hinzu kommt noch, dass Chosen das Select manipuliert. Also auch mal ohne JS probieren.

@Aybee
Copy link
Contributor

Aybee commented Jun 14, 2017

Ich habe mal einen lokalen Test mit einer statischen Seite gemacht. 25.000 Options. Chosen hängt sich da auf.

@Samson1964
Copy link

Ergänzend muß ich noch hinzufügen, das in meiner Funktion natürlich die Berücksichtigung der Elemente fehlt, die bereits ausgewählt wurden und nun altern. Ich habe das erst kürzlich in meine newslinklist-Erweiterung aufgenommen.

D.h. öffne ich ein Element vom Typ Inhaltselement, dürfen die bereits früher gewählten Einträge nicht verloren gehen. Deshalb muß beim Aufbau der SELECT-Liste der $dc->activeRecord berücksichtigt werden.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

No branches or pull requests

7 participants