it-swarm.com.de

Langsame Medienabfragen deaktivieren?

Wenn ein Benutzer einen Beitrag innerhalb des Administrators erstellt/aktualisiert, dauert es zwischen 15 und 30 Sekunden, bis dieser Vorgang abgeschlossen ist.

Der Täter scheint diese langsame Abfrage zu sein:

SELECT ID
FROM wp_posts
WHERE post_type = 'attachment'
AND post_mime_type LIKE 'video%'
LIMIT 1

Dies ist ein bekannter Fehler und das Kernteam arbeitet daran. In der Zwischenzeit möchte ich diese Abfrage jedoch deaktivieren können. Kann ich das in meiner functions.php Datei mit etwas wie dem pre_get_posts Filter machen?

3
bigmike7801

Lösung für WordPress-Versionen> = 4.7.4 (4.8)

Ticket # 31071 führt Patches mit neuen Filtern ein, um drei mögliche langsame Medienabfragen in der Funktion wp_enqueue_media() zu überschreiben:

  • media_library_show_audio_playlist (@param bool | null)

    Aus dem Inline-Dokument: Ob die Schaltfläche oder null angezeigt werden soll, hängt davon ab, ob Audiodateien in der Medienbibliothek vorhanden sind.

  • media_library_show_video_playlist (@param bool | null)

    Aus dem Inline-Dokument: Ob die Schaltfläche oder null angezeigt werden soll, hängt davon ab, ob Videodateien in der Medienbibliothek vorhanden sind.

  • media_library_months_with_files (@param array | null)

    Aus dem Inline-Dokument: Ein Array von Objekten mit den Eigenschaften month und year oder null (oder einem anderen Nicht-Array-Wert) für das Standardverhalten.

Beispiel:

Hier ist ein Demo-Plugin:

<?php
/**
  * Plugin Name:  Override Possible Slow Media Queries
  * Plugin URI:   https://wordpress.stackexchange.com/a/200383/26350
  */

// Always show audio button
add_filter( 'media_library_show_audio_playlist', '__return_true' );

// Always show video button
add_filter( 'media_library_show_video_playlist', '__return_true' );

// Cache media library file months with the transients API
add_filter( 'media_library_months_with_files', function( $months )
{
    // Generate file months when it's not cached or the transient has expired
    if ( false === ( $months = get_transient( 'wpse_media_library_months_with_files' ) ) )
    {
        global $wpdb;

        /**
         * Note that we want to avoid returning non-array file months,  
         * to avoid running the slow query twice.
         *
         * From the Codex for wpdb::get_results( $query, $output_type ):
         *
         * "If no matching rows are found, or if there is a 
         *  database error, the return value will be an empty array.
         *  If your $query string is empty, or you pass an invalid 
         *  $output_type, NULL will be returned."
         *
         * So it looks like we're covered, as we're not dealing with 
         * empty query or a wrong return type.
         */
        $months = $wpdb->get_results( $wpdb->prepare( "
            SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
            FROM $wpdb->posts
            WHERE post_type = %s
            ORDER BY post_date DESC
         ", 'attachment' ) );

        // Cache the results
        set_transient(
            'wpse_media_library_months_with_files',
                $months,
                12 * HOUR_IN_SECONDS   // <-- Override to your needs!
             );
    }
    return $months;
} );

Beachten Sie, dass wir die Dateimonate auch mit z. B .:

$months = [
    (object) [ 'year' => 2017, 'month' => 2 ],
    (object) [ 'year' => 2017, 'month' => 1 ],
    (object) [ 'year' => 2016, 'month' => 12 ],
];

mit dem media_library_months_with_files filter.

Vorherige Antwort

Diese Abfragen befinden sich in der Funktion wp_enqueue_media():

$has_audio = $wpdb->get_var( "
            SELECT ID
            FROM $wpdb->posts
            WHERE post_type = 'attachment'
            AND post_mime_type LIKE 'audio%'
            LIMIT 1
    " );
 $has_video = $wpdb->get_var( "
            SELECT ID
            FROM $wpdb->posts
            WHERE post_type = 'attachment'
            AND post_mime_type LIKE 'video%'
            LIMIT 1
    " );
 $months = $wpdb->get_results( $wpdb->prepare( "
            SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
            FROM $wpdb->posts
            WHERE post_type = %s
            ORDER BY post_date DESC
    ", 'attachment' ) );

Hier ist eine Möglichkeit, diese potenziellen langsamen Abfragen zu ändern:

/**
 * Modify the potential slow $has_audio, $has_video and $months queries
 *
 * @link http://wordpress.stackexchange.com/a/200383/26350
 */
add_filter( 'media_upload_tabs', function( $tabs )
{
    add_filter( 'query', 'wpse_replace_months_sql' );
    add_filter( 'query', 'wpse_replace_audio_video_sql' );
    return $tabs;
} );

add_filter( 'media_view_settings', function( $settings )
{
    remove_filter( 'query', 'wpse_replace_months_sql' );
    remove_filter( 'query', 'wpse_replace_audio_video_sql' );
    return $settings;
} );

wo (PHP 5.4+):

/**
 * Use "SELECT false" for the $has_audio and $has_video queries
 */
function wpse_replace_audio_video_sql( $sql )
{
   global $wpdb;
   foreach( [ 'audio', 'video' ] as $type )
   {
      $find = "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' 
          AND post_mime_type LIKE '{$type}%' LIMIT 1";
      if( trim( preg_replace('/\s+/', ' ', $sql) ) == trim( preg_replace('/\s+/', ' ', $find) ) )
          return "SELECT false"; // <-- We could also use true here if needed
   }
   return $sql;
} 

und

/**
 * Replace the available months query with the current month
 */
function wpse_replace_months_sql( $sql )
{
    global $wpdb;
    $find = "SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month
        FROM {$wpdb->posts} WHERE post_type = 'attachment' ORDER BY post_date DESC";
    if( trim( preg_replace('/\s+/', ' ', $sql) ) == trim( preg_replace('/\s+/', ' ', $find) ) )
         $sql = "SELECT YEAR( CURDATE() ) as year, MONTH( CURDATE() ) as month";
    return $sql;
}

Wir könnten versuchen, dies zu verfeinern, indem wir einen has_audio- und einen has_video-Indikator in der Optionstabelle erstellen und aktualisieren, wenn wir eine Audio- oder Video-Datei hochladen/löschen.

In dem in der Frage erwähnten Trac-Ticket gibt es einen vorgeschlagenen Index :

ALTER TABLE $wpdb->posts ADD INDEX type_mime(post_type,post_mime_type)

das könnte etwas Auftrieb geben.

@ Denis-de-Bernardy gibt auch ein Beispiel für alternative Abfragen für den Monatsteil.

4
birgire