【问题标题】:Why is this group by causing a filesort?为什么这个组是通过引起文件排序的?
【发布时间】:2011-12-24 15:24:42
【问题描述】:

我有一组高度相关的表,我已将它们扁平化为两个 InnoDB 表:

mysql> desc WPropertyCube; +--------------------+----------+------ +-----+---------+----------------+ |领域 |类型 |空 |钥匙 |默认 |额外 | +--------------------+----------+------ +-----+---------+----------------+ |编号 | bigint(20) 无符号 |否 |优先级 |空 |自动增量 | | lineOfBusinessId | bigint(20) 无符号 |否 |穆尔 |空 | | | txt属性1 | varchar(125) |是 | |空 | | | txt属性2 | varchar(125) |是 | |空 | | | txt属性3 | varchar(125) |是 | |空 | | ... | txtProperty20 | varchar(125) |是 | |空 | | |查找属性 ID1 | bigint(20) 无符号 |是 | |空 | | |查找属性 ID2 | bigint(20) 无符号 |是 | |空 | | |查找属性 ID3 | bigint(20) 无符号 |是 | |空 | | ... |查找PropertyId30 | bigint(20) 无符号 |是 | |空 | | +--------------------+----------+------ +-----+---------+----------------+ mysql> 显示来自 WPropertyCube 的索引; +---------------+------------+-------- -+--------------+------------------+------------+-- ------------+----------+--------+------+----------- -+---------+--------------+ |表 |非唯一 |键名 | Seq_in_index |列名 |整理 |基数|子部分 |包装 |空 |索引类型 |评论 |索引评论 | +---------------+------------+-------- -+--------------+------------------+------------+-- ------------+----------+--------+------+----------- -+---------+--------------+ | WPropertyCube | 0 |初级 | 1 |编号 |一个 | 379383 |空 |空 | | BTREE | | | | WPropertyCube | 1 | WPropertyCube_idx01 | 1 | lineOfBusinessId |一个 | 204 |空 |空 | | BTREE | | | +---------------+------------+-------- -+--------------+------------------+------------+-- ------------+----------+--------+------+----------- -+---------+--------------+ mysql> desc WMeasureCube; +----------------+---------------------+------+--- --+---------+--------+ |领域 |类型 |空 |钥匙 |默认 |额外 | +----------------+---------------------+------+--- --+---------+--------+ | propertyCubeId | bigint(20) 无符号 |否 |优先级 |空 | | |行动日期 |日期时间 |否 |优先级 |空 | | |测量1 |十进制(15,6) |是 | |空 | | |测量2 |十进制(15,6) |是 | |空 | | |测量3 |十进制(15,6) |是 | |空 | | ... |测量30 |十进制(15,6) |是 | |空 | | +----------------+---------------------+------+--- --+---------+--------+ mysql> 显示来自 WMeasureCube 的索引; +--------------+------------+-------------------+- -------------+----------------+------------+------ ------+------------+--------+------+------------+--- ------+----------------+ |表 |非唯一 |键名 | Seq_in_index |列名 |整理 |基数|子部分 |包装 |空 |索引类型 |评论 |索引评论 | +--------------+------------+-------------------+- -------------+----------------+------------+------ ------+------------+--------+------+------------+--- ------+----------------+ | WMeasureCube | 0 |初级 | 1 | propertyCubeId |一个 | 18 |空 |空 | | BTREE | | | | WMeasureCube | 0 |初级 | 2 |行动日期 |一个 | 81680372 |空 |空 | | BTREE | | | | WMeasureCube | 1 | WMeasureCube_idx1 | 1 |行动日期 |一个 | 18 |空 |空 | | BTREE | | | | WMeasureCube | 1 | WMeasureCube_idx1 | 2 | propertyCubeId |一个 | 81680372 |空 |空 | | BTREE | | | +--------------+------------+-------------------+- -------------+----------------+------------+------ ------+------------+--------+------+------------+--- ------+----------------+

你可以看到我一直在玩索引,但还没有找到神奇的组合。 WPropertyCube 有 ~100K 记录,WMeasureCube 有 ~80M。我的查询是这样的:

mysql> 解释 SELECT wmc.actionDate, -> 总和(wmc.measure7), -> 总和(wmc.measure8), -> 总和(wmc.measure9) -> 来自 WMeasureCube wmc -> INNER JOIN WPropertyCube wpc -> ON wmc.propertyCubeId = wpc.id -> WPC.lineOfBusinessId 在哪里(1、2、3、4) -> AND wmc.actionDate BETWEEN '2010-06-28' AND '2010-09-26' -> 按 wmc.actionDate 分组 -> 按 wmc.actionDate 排序; +----+-------------+--------+--------+------------- ----------------+---------+---------+---------- --------------+----------+------------ ----------------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+--------+--------+------------- ----------------+---------+---------+---------- --------------+----------+------------ ----------------------+ | 1 |简单 | wmc |全部 | PRIMARY,WMeasureCube_idx1 |空 |空 |空 | 81680372 |使用哪里;使用临时的;使用文件排序 | | 1 |简单 |木塑 | eq_ref |初级,WPropertyCube_idx01 |初级 | 8 | db.wmc.propertyCubeId | 1 |使用位置 | +----+-------------+--------+--------+------------- ----------------+---------+---------+---------- --------------+----------+------------ ----------------------+

此查询将约 30K 记录聚合为约 1,000 条记录。请注意,没有索引用于访问WMeasureCube,更糟糕的是,有一个文件排序是 slooooowww。查询时间范围在 30 - 150 秒之间。令人困惑的是,如果我删除 GROUP BY:

mysql> 解释 SELECT wmc.actionDate, -> 总和(wmc.measure7), -> 总和(wmc.measure8), -> 总和(wmc.measure9) -> 来自 WMeasureCube wmc -> INNER JOIN WPropertyCube wpc -> ON wmc.propertyCubeId = wpc.id -> WPC.lineOfBusinessId 在哪里(1、2、3、4) -> AND wmc.actionDate BETWEEN '2010-06-28' AND '2010-09-26' -> 按 wmc.actionDate 排序; +----+-------------+--------+--------+------------- ----------------+---------+---------+---------- --------------+----------+--------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+--------+--------+------------- ----------------+---------+---------+---------- --------------+----------+--------------+ | 1 |简单 | wmc |全部 | PRIMARY,WMeasureCube_idx1 |空 |空 |空 | 81680372 |使用位置 | | 1 |简单 |木塑 | eq_ref |初级,WPropertyCube_idx01 |初级 | 8 | db.wmc.propertyCubeId | 1 |使用位置 | +----+-------------+--------+--------+------------- ----------------+---------+---------+---------- --------------+----------+--------------+

仍然没有使用索引,但至少没有文件排序。此查询在不到一秒的时间内始终如一地运行。这特别奇怪,因为一组列的排序在执行时间方面应该与同一组的分组一致。

如何加快查询速度?

我已尝试添加所有服务器变量,但它们占用了太多空间。所以,我添加了我认为最有帮助的那些。

mysql> 显示变量; +-------------------------------------------------- --+----------------------------------------------- -------------------------------------------------- ---------------+ |变量名 |价值 | +-------------------------------------------------- --+----------------------------------------------- -------------------------------------------------- ---------------+ |大表 |关闭 | | binlog_cache_size | 4194304 | | binlog_direct_non_transactional_updates |关闭 | |二进制日志格式 |声明 | | bulk_insert_buffer_size | 8388608 | |字符集数据库 | utf8 | |字符集文件系统 |二进制 | | default_storage_engine |数据库 | | innodb_adaptive_flushing |开 | | innodb_adaptive_hash_index |开 | | innodb_additional_mem_pool_size | 16777216 | | innodb_autoextend_increment | 8 | | innodb_autoinc_lock_mode | 1 | | innodb_buffer_pool_instances | 1 | | innodb_buffer_pool_size | 6442450944 | | innodb_change_buffering |全部 | | innodb_checksums |开 | | innodb_commit_concurrency | 0 | | innodb_concurrency_tickets | 500 | | innodb_data_file_path | ibdata1:10M:自动扩展 | | innodb_data_home_dir | | | innodb_doublewrite |开 | | innodb_fast_shutdown | 1 | | innodb_file_format |梭鱼 | | innodb_file_format_check |开 | | innodb_file_format_max |梭鱼 | | innodb_file_per_table |开 | | innodb_flush_log_at_trx_commit | 0 | | innodb_flush_method | | | innodb_force_recovery | 0 | | innodb_io_capacity | 200 | | innodb_lock_wait_timeout | 120 | | innodb_locks_unsafe_for_binlog |关闭 | | innodb_log_buffer_size | 16777216 | | innodb_log_file_size | 268435456 | | innodb_log_files_in_group | 3 | | innodb_log_group_home_dir | ./ | | innodb_max_dirty_pages_pct | 90 | | innodb_max_purge_lag | 0 | | innodb_mirrored_log_groups | 1 | | innodb_old_blocks_pct | 37 | | innodb_old_blocks_time | 0 | | innodb_open_files | 300 | | innodb_purge_batch_size | 20 | | innodb_purge_threads | 0 | | innodb_read_ahead_threshold | 56 | | innodb_read_io_threads | 8 | | innodb_replication_delay | 0 | | innodb_rollback_on_timeout |关闭 | | innodb_spin_wait_delay | 6 | | innodb_stats_on_metadata |开 | | innodb_stats_sample_pages | 8 | | innodb_strict_mode |关闭 | | innodb_support_xa |关闭 | | innodb_sync_spin_loops | 30 | | innodb_table_locks |开 | | innodb_thread_concurrency | 0 | | innodb_thread_sleep_delay | 10000 | | innodb_use_native_aio |开 | | innodb_use_sys_malloc |开 | | innodb_version | 1.1.2 | | innodb_write_io_threads | 8 | | join_buffer_size | 8388608 | | key_buffer_size | 8388608 | |大文件支持|开 | |大页面大小 | 0 | |大页 |关闭 | | last_insert_id | 0 | | max_binlog_cache_size | 18446744073709547520 | | max_binlog_size | 1073741824 | | max_heap_table_size | 536870912 | | max_join_size | 18446744073709551615 | | max_length_for_sort_data | 1024 | |最大排序长度 | 1024 | | max_sp_recursion_depth | 0 | | max_tmp_tables | 32 | | optimizer_prune_level | 1 | |优化器搜索深度 | 62 | |优化器开关 | index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,engine_condition_pushdown=on | | preload_buffer_size | 32768 | |分析 |关闭 | | profiling_history_size | 15 | |协议版本 | 10 | |伪线程 ID | 13 | |查询分配块大小 | 8192 | |查询缓存限制 | 8388608 | | query_cache_min_res_unit | 4096 | |查询缓存大小 | 134217728 | |查询缓存类型 |开 | | query_cache_wlock_invalidate |关闭 | | query_prealloc_size | 8192 | | rand_seed1 | 0 | | rand_seed2 | 0 | | range_alloc_block_size | 4096 | |读取缓冲区大小 | 8388608 | |排序缓冲区大小 | 16777216 | | sql_big_selects |开 | | sql_big_tables |关闭 | | sql_max_join_size | 18446744073709551615 | |存储引擎 |数据库 | | tmp_table_size | 536870912 | | tmpdir | /dev/shm | | tx_isolation |可重复阅读 | |版本 | 5.5.6-rc-log | |版本评论 | MySQL 社区服务器 (GPL) | | version_compile_machine | x86_64 | | version_compile_os | linux2.6 | +-------------------------------------------------- --+----------------------------------------------- -------------------------------------------------- ---------------+

[编辑] 感谢 Daniel 的建议,我已将 DATETIME 字段更改为 DATE。令人高兴的是,现在正在使用该索引。不幸的是,我们仍在进行文件分类。

+----+-------------+--------+-------+-------------- ---------------+----------+---------+-- -------------+--------+--------------- --------------------------------+ |编号 |选择类型 |表|类型 |可能的键 |关键 | key_len |参考 |行 |额外 | +----+-------------+--------+-------+-------------- ---------------+----------+---------+-- -------------+--------+--------------- --------------------------------+ | 1 |简单 |木塑 |索引 |初级,WPropertyCube_idx01 | WPropertyCube_idx01 | 8 |空 | 377500 |使用哪里;使用索引;使用临时的;使用文件排序 | | 1 |简单 | wmc |参考 | PRIMARY,WMeasureCube_idx1 |初级 | 8 | db.wpc.id | 49 |使用位置 | +----+-------------+--------+-------+-------------- ---------------+----------+---------+-- -------------+--------+--------------- --------------------------------+

【问题讨论】:

    标签: mysql


    【解决方案1】:

    我认为您的问题是日期时间列 actiondate。如果您不需要时间信息,请尝试将此列设置为日期列!那么分组应该更快并且您的索引应该可以工作。

    【讨论】:

    • 我会试试的。为什么索引会作为 DATE 而不是 DATETIME?
    • 因为例如:将一天的操作汇总给您一组。为日期时间聚合操作可为您提供 86400 (60*60*24) 组;-)
    • 我认为您的旧 actiondate 索引的基数与您表中的行大小相同。在这种情况下,不使用索引。
    • 嗯,将 DATETIME 字段转换为 DATE 字段需要一些时间,但我很高兴地说,现在正在使用索引!但是,文件排序仍然存在:(关于如何消除文件排序的任何想法?我已经用新的解释计划编辑了这个问题。
    • Filesort 来自您的 select 语句的排序......任何时候无法从索引执行排序时,它的文件排序。 mysqlperformanceblog.com/2009/03/05/…
    猜你喜欢
    • 2011-02-18
    • 2014-08-05
    • 2021-01-26
    • 2014-12-18
    • 2016-10-09
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    相关资源
    最近更新 更多