【问题标题】:mysql: how can I improve performance for this mysql select statementmysql:如何提高此 mysql select 语句的性能
【发布时间】:2011-02-22 18:39:18
【问题描述】:

我已经创建了一个 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 ||

【问题讨论】:

  • 你能告诉我们查询计划吗?使用解释dev.mysql.com/doc/refman/5.5/en/explain.html
  • 我不认为你可以改进它,因为它正在从表中加载所有数据。
  • @augusto 除非ext 上缺少可用于执行分组的索引
  • “使用临时;使用文件排序”是主要问题。如果没有 ORDER BY,查询可能会快得多。更改 sort_buffer_size 也可能有所帮助。使用 TRIGGER 避免了整个问题,您没有计算运行时间,只有在插入/更新/删除期间。

标签: mysql performance


【解决方案1】:

所写的查询总是会命中表中的每一行 - 所以它的执行速度确实是有限的。如果您真的希望此结果快速返回,您可能需要添加另一个表以保持每个 ext 的总大小,并在主表上发生操作时使用触发器更新它。

【讨论】:

    【解决方案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 秒内返回。

    【讨论】:

    • 请记住,这些值也可能在更新时发生变化 - 您还应该有一个 On Update 触发器。
    • 很好看的卡尔,我省略了它,看看是否有人在听:P
    【解决方案3】:

    由于我看不出您的 MySQL 语法有任何明显缺陷,如果您希望它比这更快,我建议您使用 NoSQL,并使用支持 Map-Reduce 的文档数据库,例如 HadoopCouchDB .您可以将它托管在 EC2 上的集群(阅读:数百台机器)上(好吧,我在开玩笑,但说真的,您可以在每个 CPU 内核上运行 1 个节点,以在 1 个机器上实现最大速度)。

    【讨论】:

    • 每个 CPU 核心 1 个节点?这听起来很有趣,你有一个链接可以进一步解释这个吗?
    【解决方案4】:

    您的查询将访问表的每条记录,因此您不想通过先访问索引然后访问表来减慢速度,因为显然这会导致表中的每条记录 2 个 IO(1用于索引,1 用于实际表数据)。

    因此第一个问题变成了如何加快全表扫描速度?

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

    或者,考虑非规范化;例如表上的触发器,它对每次插入、更新和删除的适当数据进行计数和求和,并将该值存储在另一个表中。然后查询这个另一个表中的单行数据。

    【讨论】:

      【解决方案5】:

      添加一个覆盖索引,它基本上会在内存中包含您需要的所有列。 我会推荐:alter table fileindex add index covering (ext,TotalSizeGB, size)

      应该很好用。 (希望)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-09-06
        • 2016-08-25
        • 1970-01-01
        • 2012-06-16
        • 1970-01-01
        • 1970-01-01
        • 2016-10-07
        • 2012-04-11
        相关资源
        最近更新 更多