mysql - 简单的 SELECT 查询对于大表来说很慢

标签 mysql mariadb mysql-slow-query-log

我有一个具有以下结构的表

SHOW CREATE TABLE data_temperature;

CREATE TABLE `data_temperature` (
  `temperature_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `data_id` bigint(20) unsigned NOT NULL,
  `x_id` varchar(32) DEFAULT NULL,
  `x_sn` varchar(16) DEFAULT NULL,
  `x_unit` char(1) DEFAULT NULL,
  `x_value` decimal(6,2) DEFAULT NULL,
  PRIMARY KEY (`temperature_id`),
  KEY `created` (`created`),
  KEY `data_id` (`data_id`),
  KEY `x_value` (`x_value`)
) ENGINE=InnoDB AUTO_INCREMENT=6274618 DEFAULT CHARSET=latin1

我有一个从这里提取数据的基本查询,速度非常慢。所以我将查询分解为更简单的术语,发现这个非常简单的查询很慢(17.52 秒):

SELECT data_temperature.x_value FROM data_temperature WHERE data_temperature.created BETWEEN '2015-02-02 18:28:42' AND '2015-03-04 18:28:42';

该表有 6,274,617 行。事实上,SELECT COUNT(*) FROM data_temperature 也需要 3.66 秒。

运行此查询的系统是我的开发系统,它是一个运行 Ubuntu 14.04 的四核系统、4GB RAM 和一个固态驱动器。

这是关于运行这样的查询需要多长时间,还是我做错了什么?有没有更高效的方式返回数据?

最佳答案

想想输出有多少行。想想这些行占用了多少磁盘空间。想一想磁盘的运行速度有多慢。想想你将如何处理所有这些行。 17 秒是合理的。

同样,由于这些因素中的大多数,COUNT(*) 花费了 3.66 秒。

让我们深入挖掘。

InnoDB 表上的

SELECT COUNT(*) FROM tbl 将完全扫描其中一个索引,同时计算行数。该索引可能约为 100MB。它必须从磁盘中获取所有 100MB,除了可能已经缓存的所有内容。它必须查看 600 万行中的每一行,边走边数。总计:3.66 秒。

现在让我们看看另一个查询。它更复杂,因此更慢。

您有一个适合 WHERE 子句的索引:INDEX(created)。那是在 BTree 中。首先,它会找到“2015-02-02 18:28:42”或之后的第一个条目。然后线性向前扫描,直到到达“2015-03-04 18:28:42”。这可能需要不到 3.66 秒。但是……

对于索引中的每个项目,它需要查找。它通过首先找到 PRIMARY KEY temperature_id 来获得它,它位于同一个 BTree 中,就在 created 旁边。使用temperature_id,它遍历另一个BTree,即有PK和数据的BTree,找到对应的行。它在那里找到 value。这对范围内非常 created 重复。这些查找所需的 block 将是更多 MB 的数据。

让 SELECT 运行得更快是可能的,但它只会帮助这个查询: 索引(创建,值)。这是一个“覆盖”索引。这意味着 所有 SELECT 所需的列都在索引中找到。因此,它不需要进入另一个 BTree。这可能会导致 3.66 秒或更短的时间。

关于mysql - 简单的 SELECT 查询对于大表来说很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28870832/

相关文章:

mysql - 如何在 mysql 中的三个表的另一个子查询中使用子查询?

python - 加速从 pandas dataframe 到 mysql 的数据插入

mysql - 慢查询问题 - 得到通知

MySQL SUM 查询速度极慢

mysql - 如何使用 phpmyadmin 添加删除级联和更新限制?

mysql - 将一个表连接到两个单独的一对多表

php - Wampserver 2.1 在 Windows 7 上安装后显示橙色图标

mysql - query_cache_size、Qcache_total_blocks 和 query_alloc_block_size

mysql - 数据库还原不保留表情符号

mysql - 对于这种缓慢的 MySQL 查询,最好的索引是什么? (InnoDB)