mysql:如何提高这个mysql select语句的性能

时间:2011-02-22 18:39:18

标签: mysql performance

我创建了一个sql表,我在磁盘上编制了索引文件。 桌上有超过100万条记录。 我已经为ext和size添加了索引,但执行此查询仍然需要一分钟,这告诉我ext使用的空间量。 如何提高此选择的性能?

select ext,
     ROUND((sum(size) / (1073741824))) as TotalSizeGB,
     count(*) as Count
  from fileindex
group by ext
order by TotalSizeGB desc;

解释输出:

|| *id* || *select_type* || *table*   || *type* || *possible_keys* || *key* || *key_len* || *ref*  || *rows*  || *Extra*                                      ||
|| 1    || SIMPLE        || fileindex || index  || _NULL_          || ext   || 27        || _NULL_ || 1892234 || Using index; Using temporary; Using filesort ||

5 个答案:

答案 0 :(得分:2)

使用MySQL Triggers以便将行插入到fileindex中,它会执行类似UPDATE meta SET value=value+NEW.size WHERE name='fileindex.count';的操作。

delimiter |

DROP TRIGGER fileindexafterinsert;|
CREATE TRIGGER fileindexafterinsert AFTER INSERT ON fileindex
    FOR EACH ROW BEGIN
        update meta set value=value+NEW.size where name=CONCAT('fileindex.',NEW.ext);
    END;
|
DROP TRIGGER fileindexafterdelete;|
CREATE TRIGGER fileindexafterdelete AFTER DELETE ON fileindex
    FOR EACH ROW BEGIN
        update meta set value=value-OLD.size where name=CONCAT('fileindex.',OLD.ext);
    END;
|

然后你可以做SELECT * FROM meta WHERE name='fileindex.exe' LIMIT 1,它应该在不到0.01秒内返回。

答案 1 :(得分:2)

写入的查询总是会触及表中的每一行 - 因此它的执行速度确实存在限制。如果你真的希望这个结果快速返回,你可能想要添加另一个表来保持每个ext的总大小,并且只要在主表上进行操作就用触发器更新它。

答案 2 :(得分:0)

由于我看不到你的MySQL语法有任何明显的缺陷,如果你想要比它快,我建议去NoSQL,并使用支持Map-Reduce的文档数据库,如HadoopCouchDB。您可以在EC2上的一个集群(读取:数百个)上托管这个(好吧,我在开玩笑,但是认真的,你可以在每个CPU核心上运行1个节点,以便在1个盒子上获得最大速度)。

答案 3 :(得分:0)

您的查询将打到表的每个记录,因此您不希望通过首先点击索引然后按表来减慢速度,因为显然这将导致表中每个记录2个IO(1索引和实际表数据的1)。

因此,第一个问题是如何加快全表扫描?

调整IO。您的磁盘是快速,碎片整理,不共享(与其他数据,应用程序等)等。

或者,考虑非规范化;例如表上的触发器,用于计算每个插入,更新和删除的相应数据并将其相加,并将此值存储在另一个表中。然后在另一个表中查询单行数据。

答案 4 :(得分:0)

添加覆盖索引,它基本上具有内存中所需的所有列。 我建议:alter table fileindex add index covering (ext,TotalSizeGB, size)

应该运作良好。 (希望)