我有一张 100k 行的表
创建表`small_table`( `pk` int(11) NOT NULL AUTO_INCREMENT, `varc` varchar(255) 默认为空, `txt` 文本, 主键 (`pk`) ) ENGINE=InnoDB AUTO_INCREMENT=103925 默认字符集=utf8
我执行了以下查询
select varc,count(*) from small_table group by varc;
和我一样
+--------------------+----------+ | 状态 | 持续时间 | +--------------------+----------+ | 开始| 0.000060 | | 检查权限 | 0.000010 | | 打开表格 | 0.004685 | | 初始化 | 0.000025 | | 系统锁 | 0.000006 | | 优化 | 0.000002 | | 统计 | 0.000010 | | 准备 | 0.000006 | | 创建 tmp 表 | 0.000020 | | 排序结果 | 0.000003 | | 执行 | 0.000005 | | 发送数据 | 0.001720 | | 创建排序索引 | 0.000033 | | 结束 | 0.000002 | | 查询结束 | 0.000004 | | 删除 tmp 表 | 0.000004 | | 查询结束 | 0.000002 | | 关闭表 | 0.000004 | | 释放物品 | 0.000015 | | 清理 | 0.000007 | +--------------------+----------+
该配置文件具有正在创建 tmp 表状态(根据 mysql 文档,这意味着 tmp 表是在内存或磁盘中创建的)。我怀疑配置文件没有Copying to tmp table状态(在状态期间,服务器将复制到内存中的临时表。)我的假设是它已经创建了一个 tmp 表并且没有使用它。我对吗?
我的复制到 tmp 表状态在哪里?
它只是名称略有不同。它是“Creating tmp table”,这也更有意义。MySQL 知道,将需要一个临时表,所以它会即时生成它。状态名称“复制到 tmp 表”只是选择不当。
我通常发现 Profile 没用。通常“发送数据”是最上面的条目。这没有给出应该修复什么以提高性能的线索。
虽然没有“copy to tmp table”,但是有一个相当大的“opening tables”。但是不知道它是你的表还是tmp表。有“创建 tmp 表”。tmp 表可能在内存中;也就是说,没有实际的磁盘表。
有两种查询方式——
在所有的内存中构建一个哈希
varcs
;扫描表,增加散列中的条目;对结果进行排序;交付它。首先对表进行排序(在您的情况下,这涉及 RAM 中的 tmp 表);然后是一个简单的表扫描,一次构建一个
COUNT
。我不知道优化器何时会选择一个而不是另一个。但它总是涉及表扫描,这往往是花费的大部分时间(尽管它没有显示在配置文件中)。
如果你碰巧有
INDEX(varc)
,它会完成:但是...当一个查询花费的时间低于 10 毫秒时,就不值得对其进行剖析——获得的东西很少,值得优化的东西也很少。