It seems, on databases with loads of revision rows (ie enwiki, not testwiki), although the EXPLAIN is sane, it's doing something stupid (table scan? I've nfi). So, as any revision id's less than 0 aren't valid, just prefilter them from the database SQL query
mysql> DESCRIBE SELECT /* ApiPageSet::initFromRevIDs */ rev_id,rev_page FROM `revision`,`page` WHERE rev_id IN ('10','20','30','40','-50','60') AND (rev_page = page_id);
+----+-------------+----------+-------+-------------------------------+---------+---------+-----------------------+-------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+-------------------------------+---------+---------+-----------------------+-------+--------------------------+
| 1 | SIMPLE | page | index | PRIMARY | PRIMARY | 4 | NULL | 22982 | Using index |
| 1 | SIMPLE | revision | ref | PRIMARY,rev_id,page_timestamp | PRIMARY | 4 | testwiki.page.page_id | 1 | Using where; Using index |
+----+-------------+----------+-------+-------------------------------+---------+---------+-----------------------+-------+--------------------------+
* (bug 29221) Expose oldrevid in watchlist output
* (bug 29267) always give the servername for meta=siteinfo&siprop=dbrepllag
* (bug 28897) rvparse doesn’t seem to work with rvsection
+* (bug 25734) API: possible issue with revids validation
=== Languages updated in 1.19 ===
$pageids = array();
$remaining = array_flip( $revids );
+ // bug 25734 API: possible issue with revids validation
+ // It seems with a load of revision rows, MySQL gets upset
+ // Remove any < 0 revids, as they can't be valid
+ foreach( $revids as $i => $revid ) {
+ if ( $revid < 0 ) {
+ unset( $revids[$i] );
+ }
+ }
+
$tables = array( 'revision', 'page' );
$fields = array( 'rev_id', 'rev_page' );
$where = array( 'rev_id' => $revids, 'rev_page = page_id' );