API performance enhancements (bug 13511):
authorRoan Kattouw <catrope@users.mediawiki.org>
Wed, 26 Mar 2008 13:43:11 +0000 (13:43 +0000)
committerRoan Kattouw <catrope@users.mediawiki.org>
Wed, 26 Mar 2008 13:43:11 +0000 (13:43 +0000)
* Replaced $wgAPIUCUserPrefixMinLength with the more generic $wgAPIMaxDBRows
* Added ApiBase::checkRowCount() which checks whether the amount of rows to be scanned is acceptable (i.e. <$wgAPIMaxDBRows). Not using this anywhere (yet?), but it's nice to have
* Killed a filesort in the usercontribs query, query is now indexed nicely
* Dropped the minimum length for ucuserprefix since it's no longer needed (query optimized)
* Removed drnamespace from list=deletedrevs (filesorts 8M rows for drnamespace=0)
* Support multiple orderings in ApiBase::addWhereRange()

RELEASE-NOTES
includes/DefaultSettings.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryDeletedrevs.php
includes/api/ApiQueryUserContributions.php

index 5418651..a665820 100644 (file)
@@ -167,6 +167,7 @@ it from source control: http://www.mediawiki.org/wiki/Download_from_SVN
 * Added inprop=talkid,subjectid to prop=info
 * Added help text message that specifies whether a module is POST-only
 * Added createonly parameter to action=edit
+* Replaced $wgAPIUCUserPrefixMinLength by the more generic $wgAPIMaxDBRows
 
 === Languages updated in 1.13 ===
 
index b34bf3d..132376e 100644 (file)
@@ -2877,10 +2877,10 @@ $wgEnableWriteAPI = false;
 $wgAPIModules = array();
 
 /**
- * Minimum length of list=usercontribs's ucuserprefix parameter
- * Setting this to a low value can open DOS windows on large wikis
+ * Maximum amount of rows to scan in a DB query in the API
+ * The default value is generally fine
  */
-$wgAPIUCUserPrefixMinLength = 3;
+$wgAPIMaxDBRows = 5000;
 
 /**
  * Parser test suite files to be run by parserTests.php when no specific
index 98a6ef3..62ba881 100644 (file)
@@ -111,8 +111,11 @@ abstract class ApiQueryBase extends ApiBase {
                if (!is_null($end))
                        $this->addWhere($field . $before . $db->addQuotes($end));
                
+               $order = $field . ($isDirNewer ? '' : ' DESC');
                if (!isset($this->options['ORDER BY']))
-                       $this->addOption('ORDER BY', $field . ($isDirNewer ? '' : ' DESC'));
+                       $this->addOption('ORDER BY', $order);
+               else
+                       $this->addOption('ORDER BY', $this->options['ORDER BY'] . ', ' . $order);
        }
 
        protected function addOption($name, $value = null) {
@@ -134,6 +137,18 @@ abstract class ApiQueryBase extends ApiBase {
                return $res;
        }
 
+       protected function checkRowCount() {
+               $db = $this->getDB();
+               $this->profileDBIn();
+               $rowcount = $db->estimateRowCount($this->tables, $this->fields, $this->where, __METHOD__, $this->options);
+               $this->profileDBOut();
+               
+               global $wgAPIMaxDBRows;
+               if($rowcount > $wgAPIMaxDBRows)
+                       return false;
+               return true;
+       }
+
        public static function addTitleInfo(&$arr, $title, $prefix='') {
                $arr[$prefix . 'ns'] = intval($title->getNamespace());
                $arr[$prefix . 'title'] = $title->getPrefixedText();
index 76e6eb1..bdd9cc1 100644 (file)
@@ -111,8 +111,6 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
 
                $this->addOption('LIMIT', $params['limit'] + 1);
                $this->addWhereRange('ar_timestamp', $params['dir'], $params['start'], $params['end']);
-               if(isset($params['namespace']))
-                       $this->addWhereFld('ar_namespace', $params['namespace']);
                $res = $this->select(__METHOD__);
                $pages = array();
                $count = 0;
@@ -183,10 +181,6 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                                ),
                                ApiBase :: PARAM_DFLT => 'older'
                        ),
-                       'namespace' => array(
-                               ApiBase :: PARAM_ISMULTI => true,
-                               ApiBase :: PARAM_TYPE => 'namespace'
-                       ),
                        'limit' => array(
                                ApiBase :: PARAM_DFLT => 10,
                                ApiBase :: PARAM_TYPE => 'limit',
@@ -215,7 +209,6 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
                        'start' => 'The timestamp to start enumerating from',
                        'end' => 'The timestamp to stop enumerating at',
                        'dir' => 'The direction in which to enumerate',
-                       'namespace' => 'The namespaces to search in',
                        'limit' => 'The maximum amount of revisions to list',
                        'prop' => 'Which properties to get'
                );
@@ -227,8 +220,8 @@ class ApiQueryDeletedrevs extends ApiQueryBase {
 
        protected function getExamples() {
                return array (
-                       'List the first 50 deleted revisions in the Category and Category talk namespaces',
-                       '  api.php?action=query&list=deletedrevs&drdir=newer&drlimit=50&drnamespace=14|15',
+                       'List the first 50 deleted revisions',
+                       '  api.php?action=query&list=deletedrevs&drdir=newer&drlimit=50',
                        'List the last deleted revisions of Main Page and Talk:Main Page, with content:',
                        '  api.php?action=query&list=deletedrevs&titles=Main%20Page|Talk:Main%20Page&drprop=user|comment|content'
                );
index 59a469f..672c16c 100644 (file)
@@ -62,10 +62,6 @@ class ApiQueryContributions extends ApiQueryBase {
 
                if(isset($this->params['userprefix']))
                {
-                       global $wgAPIUCUserPrefixMinLength;
-                       if(strlen($this->params['userprefix']) < $wgAPIUCUserPrefixMinLength)
-                               $this->dieUsage("User prefixes must be at least $wgAPIUCUserPrefixMinLength characters", 'userprefix-tooshort');
-
                        $this->prefixMode = true;
                        $this->userprefix = $this->params['userprefix'];
                }
@@ -145,6 +141,9 @@ class ApiQueryContributions extends ApiQueryBase {
                else 
                        $this->addWhereFld( 'rev_user_text', $this->usernames );
                // ... and in the specified timeframe.
+               // Ensure the same sort order for rev_user_text and rev_timestamp
+               // so our query is indexed
+               $this->addWhereRange('rev_user_text', $this->params['dir'], null, null);
                $this->addWhereRange('rev_timestamp', 
                        $this->params['dir'], $this->params['start'], $this->params['end'] );
                $this->addWhereFld('page_namespace', $this->params['namespace']);