使用大数据提高MySQL JOIN的速度

时间:2016-09-12 22:53:57

标签: mysql performance loops join

下面是我要从中获取数据的两个表(注意这些是虚拟数据库,所以不要注意我正在拉的数据)

> DESCRIBE bigdata;

+----------------+----------------------+------+-----+---------+-------+
| Field          | Type                 | Null | Key | Default | Extra |
+----------------+----------------------+------+-----+---------+-------+
| galaxy         | int(2)               | NO   | PRI | 0       |       |
| system         | int(3)               | NO   | PRI | 0       |       |
| planet         | int(2)               | NO   | PRI | 0       |       |
| ogame_playerid | int(11) unsigned     | NO   | MUL | 0       |       |
| moon           | enum('true','false') | NO   |     | false   |       |
| moonsize       | smallint(5) unsigned | NO   |     | 0       |       |
| metal          | int(10) unsigned     | NO   |     | 0       |       |
| crystal        | int(10) unsigned     | NO   |     | 0       |       |
| planetname     | varchar(40)          | NO   |     |         |       |
+----------------+----------------------+------+-----+---------+-------+

还将CREATE TABLE设置为@drew请求

CREATE TABLE `bigdata` (
    `galaxy` INT(2) NOT NULL DEFAULT '0',
    `system` INT(3) NOT NULL DEFAULT '0',
    `planet` INT(2) NOT NULL DEFAULT '0',
    `ogame_playerid` INT(11) UNSIGNED NOT NULL DEFAULT '0',
    `moon` ENUM('true','false') NOT NULL DEFAULT 'false',
    `moonsize` SMALLINT(5) UNSIGNED NOT NULL DEFAULT '0',
    `metal` INT(10) UNSIGNED NOT NULL DEFAULT '0',
    `crystal` INT(10) UNSIGNED NOT NULL DEFAULT '0',
    `planetname` VARCHAR(40) NOT NULL DEFAULT '',
    PRIMARY KEY (`galaxy`, `system`, `planet`),
    INDEX `player_id` (`ogame_playerid`)
)
COLLATE='utf8_general_ci'
ENGINE=MyISAM;

和第二个表(注意有更多用户ID)

SELECT * FROM smalldata WHERE userid = 1;
+----+--------+----------------+---------------------+
| id | userid | ip             | logintime           |
+----+--------+----------------+---------------------+
|  1 |      1 | 127.0.0.1      | 2016-02-25 13:50:59 |
|  2 |      1 | ::1            | 2016-02-29 23:22:18 |
|  3 |      1 | 127.0.0.1      | 2016-03-14 22:52:22 |
|  4 |      1 | 127.0.0.1      | 2016-03-22 23:27:02 |
+----+--------+----------------+---------------------+

我的查询如下

SELECT smalldata.id, SUM(bigdata.planet) 
FROM smalldata LEFT JOIN bigdata ON smalldata.id = bigdata.galaxy 
WHERE smalldata.userid = 1 
GROUP BY smalldata.id;

我担心的是,如果我运行此类查询以同时自动化所有4个smalldata的ID上的SELECTion,则需要大约10秒才能完成。但是,如果我跳过LEFT JOIN并在bigdata上执行4次invidual查询,从而“硬编码”WHERE galaxy = 1(or 2,3,4 respectively),则每个大约需要0.05秒。

我想知道为什么会这样。我认为LEFT JOIN可能会利用bigdata中我没有使用的(我没有选择的)列中的大量数据,例如月亮,月亮等等。也许可能是JOIN本身很耗时,实际上我可以从bigdata执行4个选择而不实际加入这些表。

我在这里滥用加入吗?

1 个答案:

答案 0 :(得分:1)

尝试编写如下代码:

SELECT smalldata.id,
       (SELECT SUM(bigdata.planet) 
        FROM bigdata 
        WHERE smalldata.id = bigdata.galaxy 
       )
FROM smalldata
WHERE smalldata.userid = 1 ;

确保您在smalldata(userid, id)上有索引。根据您的描述,您似乎在bigdata上有正确的索引(galaxy应该是索引中的第一个键,planet也应该在索引中。