简体   繁体   中英

Improving query performance with Join, Full Table Scan

I am trying to improve the query performance on a stats reporting website for a Battlefield game, and am having a little bit of trouble with a very specific query. The issue I am having is that EXPLAIN is stating this query is doing a full table scan. This is troublesome because I expect this table to get very large (potentially 1 million rows or more). I am using MySQL 5.7 as my database of choice.

Here is my table and Query: http://pastebin.com/DsiGe2UB

    --
    -- Table structure for table `player_kit`
    --

    CREATE TABLE `player_kit` (
      `id` TINYINT UNSIGNED NOT NULL,
      `pid` INT UNSIGNED NOT NULL,
      `time` INT UNSIGNED NOT NULL DEFAULT 0,
      `kills` MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
      `deaths` MEDIUMINT UNSIGNED NOT NULL DEFAULT 0,
      PRIMARY KEY(`pid`,`id`),
      FOREIGN KEY(`pid`) REFERENCES player(`id`) ON DELETE CASCADE ON UPDATE CASCADE,
      FOREIGN KEY(`id`) REFERENCES kit(`id`) ON DELETE RESTRICT ON UPDATE CASCADE
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

  ALTER TABLE `bf2stats`.`player_kit` ADD INDEX `reverse_ids` (`id`, `pid`);


    --
    -- My Full Scanning Query
    -- SELECTS players, ordering them by kills and time in kit
    --
    SELECT p.name, p.rank, p.country, k.pid, k.kills, k.deaths, k.time
    FROM player_kit AS k
      INNER JOIN player AS p ON k.pid = p.id
    WHERE k.id = 0 AND k.kills > 0
    ORDER BY kills DESC, time DESC
    LIMIT 0, 40

    --
    -- EXPLAIN results by MySQL
    --
    id select_type table partitions type possible_keys key key_len ref rows filtered Extra
    1 SIMPLE k NULL ref PRIMARY 1 const 75 32.11 Using index condition; Using where; Using filesort
    1 SIMPLE p NULL eq_ref PRIMARY PRIMARY 4 bf2stats.k.pid 1 100.00 NULL

    --
    -- Additional Tables just in case, for reference
    --
    --
    -- Table structure for table `kit`
    --

    CREATE TABLE `kit` (
      `id` TINYINT UNSIGNED,
      `name` VARCHAR(32) NOT NULL,
      PRIMARY KEY(`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    --
    -- Table structure for table `player`
    --

    CREATE TABLE `player` (
      `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
      `name` VARCHAR(32) UNIQUE NOT NULL,
      `rank` TINYINT NOT NULL DEFAULT 0,
      `country` CHAR(2) NOT NULL DEFAULT 'xx',
      PRIMARY KEY(`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Here is the explain from phpMyAdmin: 在此处输入图片说明

I am hoping that one of you can help me improve the performance of this query, since any kind of index I have put on it does not seem to help much.

For this query:

SELECT p.name, p.rank, p.country, k.pid, k.kills, k.deaths, k.time
FROM player_kit k INNER JOIN
     player p
     ON k.pid = p.id
WHERE k.id = 0 AND k.kills > 0
ORDER BY kills DESC, time DESC
LIMIT 0, 40;

The optimal indexes are:

  • player_kit(id, kills, pid)
  • player(id) -- if this is not already there

You can also add the other columns in the index to get a covering index for the query.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM