From 08f746478afda38fa8301c82f2ee0e5cef36aefe Mon Sep 17 00:00:00 2001 From: Roan Kattouw Date: Thu, 4 May 2017 18:04:58 -0700 Subject: [PATCH] ApiQueryTags: Use cached statistics instead of querying hit counts ourselves The hit count query was quite slow. Unfortunately, it seems that we do need tagUsageStatistics() even when hitcounts are not requested, because it might list additional tags that aren't listed by the list*Tags() functions. I don't know if this can happen in practice, but all the code around tags seems to operate as if it might. Bug: T164552 Change-Id: Ifccf7f5ac7a1220ff67a68589398cbf30aefd3ad --- includes/api/ApiQueryTags.php | 27 +++++++-------------------- 1 file changed, 7 insertions(+), 20 deletions(-) diff --git a/includes/api/ApiQueryTags.php b/includes/api/ApiQueryTags.php index be67dd249b..1b154faecb 100644 --- a/includes/api/ApiQueryTags.php +++ b/includes/api/ApiQueryTags.php @@ -53,37 +53,24 @@ class ApiQueryTags extends ApiQueryBase { $softwareDefinedTags = array_fill_keys( ChangeTags::listSoftwareDefinedTags(), 0 ); $explicitlyDefinedTags = array_fill_keys( ChangeTags::listExplicitlyDefinedTags(), 0 ); $softwareActivatedTags = array_fill_keys( ChangeTags::listSoftwareActivatedTags(), 0 ); + $tagStats = ChangeTags::tagUsageStatistics(); - $definedTags = array_merge( $softwareDefinedTags, $explicitlyDefinedTags ); + $tagHitcounts = array_merge( $softwareDefinedTags, $explicitlyDefinedTags, $tagStats ); + $tags = array_keys( $tagHitcounts ); # Fetch defined tags that aren't past the continuation if ( $params['continue'] !== null ) { $cont = $params['continue']; - $tags = array_filter( array_keys( $definedTags ), function ( $v ) use ( $cont ) { + $tags = array_filter( $tags, function ( $v ) use ( $cont ) { return $v >= $cont; } ); - $tags = array_fill_keys( $tags, 0 ); - } else { - $tags = $definedTags; - } - - # Merge in all used tags - $this->addTables( 'change_tag' ); - $this->addFields( 'ct_tag' ); - $this->addFields( [ 'hitcount' => $fld_hitcount ? 'COUNT(*)' : '0' ] ); - $this->addOption( 'LIMIT', $limit + 1 ); - $this->addOption( 'GROUP BY', 'ct_tag' ); - $this->addWhereRange( 'ct_tag', 'newer', $params['continue'], null ); - $res = $this->select( __METHOD__ ); - foreach ( $res as $row ) { - $tags[$row->ct_tag] = (int)$row->hitcount; } # Now make sure the array is sorted for proper continuation - ksort( $tags ); + sort( $tags ); $count = 0; - foreach ( $tags as $tagName => $hitcount ) { + foreach ( $tags as $tagName ) { if ( ++$count > $limit ) { $this->setContinueEnumParameter( 'continue', $tagName ); break; @@ -102,7 +89,7 @@ class ApiQueryTags extends ApiQueryBase { } if ( $fld_hitcount ) { - $tag['hitcount'] = $hitcount; + $tag['hitcount'] = intval( $tagHitcounts[$tagName] ); } $isSoftware = isset( $softwareDefinedTags[$tagName] ); -- 2.20.1