MySQL MyISAM排序查询使其变慢

时间:2014-04-12 22:33:07

标签: mysql performance sorting sql-order-by myisam

我在Windows Server 2008(使用4GB RAM)上使用MySQL 5.1并具有以下配置:

我有2个MyISAM表。一个是在1个数据库(DB1)中,有14列,主要是varchar。该表有大约5,000,000行,下面是DB1.games表。它在GameNumber(int(10))上有一个主键。

另一个表是DB2.gameposition,由GameNumber列组成(链接到 DB1.games)和PositionCode(int(10))。该表有大约400,000,000行,并且在PositionCode上有一个索引IX_PositionCode。

这两个数据库位于同一台服务器上。

我想在DB2.gameposition上运行查询以查找特定的PositionCode,并将结果按链接DB1.games.Yr字段排序(smallint(6) - 这表示年份)。我最近才介绍的结果排序。 DB1.games中的这个Yr字段有一个索引。

在我的存储过程中,我执行以下操作:

CREATE TEMPORARY TABLE tblGameNumbers(GameNumber INT UNSIGNED NOT NULL PRIMARY KEY);

INSERT INTO tblGameNumbers(GameNumber) 
SELECT DISTINCT gp.GameNumber 
FROM DB2.gameposition gp 
WHERE PositionCode = var_PositionCode LIMIT 1000;

我只需要1000就可以更快地使用

然后将其加入DB1.games表。

为了从中生成一个EXPLAIN,我取出了临时表(我在存储过程中使用)并重构它,如下面的内部子查询所示:

EXPLAIN 
SELECT * 
FROM DB1.games g 
INNER JOIN (SELECT DISTINCT gp.GameNumber 
            FROM DB2.gameposition gp 
            WHERE PositionCode = 669312116 LIMIT 1000
   ) B ON g.GameNumber = B.GameNumber 
ORDER BY g.Yr DESC 
LIMIT 0,28

运行上面的EXPLAIN,我看到以下内容:

1, 'PRIMARY', '', 'ALL', '', '', '', '', 1000, 'Using temporary; Using filesort'
1, 'PRIMARY', 'g', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'B.GameNumber', 1, ''
2, 'DERIVED', 'gp', 'ref', 'IX_PositionCode', 'IX_PositionCode', '4', '', 1889846, 'Using temporary'

在我引入ORDER BY子句之前,查询几乎是即时的。现在,有时它很快(取决于不同的PositionCode),但有时它可能需要10秒才能返回行。在我介绍排序之前,它总是几乎是瞬间完成的。不幸的是,我不太精通解释EXPLAIN输出。或者如何更快地进行查询。

非常感谢任何帮助!

提前致谢, 添

1 个答案:

答案 0 :(得分:0)

如果没有order by,则limit表示返回前28个结果,然后查询停止。使用order by,需要检索所有结果,以便对它们进行排序,并返回前28个。

说明显示MySql在做什么:

sort 5000000 games records by yr
for each games record from sorted list
    get the games record by primary key (to get all the columns)
    read gamepositions by position code
        if it does not match gamenumber, discard it
        when 1000 matches found, stop reading
    end read
end for

请改为尝试:

select distinct ... from gameposition gp
inner join games g on g.gamenumber = gp.gamenumber
where gp.positioncode = ...
order by g.yr limit ...