我创建了一个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 ||
答案 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的文档数据库,如Hadoop或CouchDB。您可以在EC2上的一个集群(读取:数百个)上托管这个(好吧,我在开玩笑,但是认真的,你可以在每个CPU核心上运行1个节点,以便在1个盒子上获得最大速度)。
答案 3 :(得分:0)
您的查询将打到表的每个记录,因此您不希望通过首先点击索引然后按表来减慢速度,因为显然这将导致表中每个记录2个IO(1索引和实际表数据的1)。
因此,第一个问题是如何加快全表扫描?
调整IO。您的磁盘是快速,碎片整理,不共享(与其他数据,应用程序等)等。
或者,考虑非规范化;例如表上的触发器,用于计算每个插入,更新和删除的相应数据并将其相加,并将此值存储在另一个表中。然后在另一个表中查询单行数据。
答案 4 :(得分:0)
添加覆盖索引,它基本上具有内存中所需的所有列。
我建议:alter table fileindex add index covering (ext,TotalSizeGB, size)
应该运作良好。 (希望)