Add STRAIGHT_JOIN to ApiQueryLogEvents and LogPager to avoid planner oddness
authorBrad Jorsch <bjorsch@wikimedia.org>
Tue, 16 Apr 2019 17:45:32 +0000 (13:45 -0400)
committerBrad Jorsch <bjorsch@wikimedia.org>
Tue, 23 Apr 2019 14:00:21 +0000 (10:00 -0400)
For some unknown reason, when the `actor` table has few enough rows (or
few enough compared to `logging`) MariaDB 10.1.37 decides it makes more
sense to fetch everything from `actor` + `logging` and filesort rather than
fetching the limited number of rows from `logging`.

We can work around it by telling it to not reorder the query.

Bug: T220999
Bug: T221458
Change-Id: I9da981c09f18ba72efeeb8279aad99eb21af699a

includes/api/ApiQueryLogEvents.php
includes/logging/LogPager.php

index 7798688..962d956 100644 (file)
@@ -238,6 +238,14 @@ class ApiQueryLogEvents extends ApiQueryBase {
                        }
                }
 
+               // T220999: MySQL/MariaDB (10.1.37) can sometimes irrationally decide that querying `actor` before
+               // `logging` and filesorting is somehow better than querying $limit+1 rows from `logging`.
+               // Tell it not to reorder the query. But not when `letag` was used, as it seems as likely
+               // to be harmed as helped in that case.
+               if ( $params['tag'] === null ) {
+                       $this->addOption( 'STRAIGHT_JOIN' );
+               }
+
                $count = 0;
                $res = $this->select( __METHOD__ );
                $result = $this->getResult();
index 801c474..0eeb544 100644 (file)
@@ -335,6 +335,14 @@ class LogPager extends ReverseChronologicalPager {
                # Don't show duplicate rows when using log_search
                $joins['log_search'] = [ 'JOIN', 'ls_log_id=log_id' ];
 
+               // T221458: MySQL/MariaDB (10.1.37) can sometimes irrationally decide that querying `actor` before
+               // `logging` and filesorting is somehow better than querying $limit+1 rows from `logging`.
+               // Tell it not to reorder the query. But not when tag filtering was used, as it seems as likely
+               // to be harmed as helped in that case.
+               if ( !$this->mTagFilter ) {
+                       $options[] = 'STRAIGHT_JOIN';
+               }
+
                $info = [
                        'tables' => $tables,
                        'fields' => $fields,