- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我通过 Amazon could service 使用默认设置的 MySQL 服务器。 mytable
涉及的表是InnoDB
类型,大约有10亿行。查询是:
select count(*), avg(`01`) from mytable where `date` = "2017-11-01";
执行需要将近 10 分钟。我有一个关于 date
的索引。此查询的 EXPLAIN
是:
+----+-------------+---------------+------+---------------+------+---------+-------+---------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------------+------+---------------+------+---------+-------+---------+-------+
| 1 | SIMPLE | mytable | ref | date | date | 3 | const | 1411576 | NULL |
+----+-------------+---------------+------+---------------+------+---------+-------+---------+-------+
这个表的索引是:
+---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| mytable | 0 | PRIMARY | 1 | ESI | A | 60398679 | NULL | NULL | | BTREE | | |
| mytable | 0 | PRIMARY | 2 | date | A | 1026777555 | NULL | NULL | | BTREE | | |
| mytable | 1 | lse_cd | 1 | lse_cd | A | 1919210 | NULL | NULL | YES | BTREE | | |
| mytable | 1 | zone | 1 | zone | A | 732366 | NULL | NULL | YES | BTREE | | |
| mytable | 1 | date | 1 | date | A | 85564796 | NULL | NULL | | BTREE | | |
| mytable | 1 | ESI_index | 1 | ESI | A | 6937686 | NULL | NULL | | BTREE | | |
+---------------+------------+-----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
如果我删除 AVG()
:
select count(*) from mytable where `date` = "2017-11-01";
返回计数只需要 0.15 秒。这个特定查询的计数是692792;其他 date
的计数类似。
我没有关于 01
的索引。这是一个问题吗?为什么 AVG()
需要这么长时间来计算?一定是我哪里做的不对。
欢迎任何建议!
最佳答案
要计算具有特定日期的行数,MySQL 必须在索引中找到该值(这非常快,毕竟这是创建索引的目的),然后读取后续条目 index 直到找到下一个日期。根据 esi
的数据类型,这将总结为读取一些 MB 的数据来计算您的 700k 行。读取一些 MB 不会花费太多时间(并且该数据甚至可能已经缓存在缓冲池中,具体取决于您使用索引的频率)。
要计算未包含在索引中的列的平均值,MySQL 将再次使用索引查找该日期的所有行(与之前相同)。但是另外,对于它找到的每一行,它必须读取该行的实际表数据,这意味着使用主键来定位该行,读取一些字节,并重复这个 700k 次。这"random access"比第一种情况下的顺序读取慢很多。 (由于“一些字节”是 innodb_page_size
(默认为 16KB)的问题变得更糟,因此与 count(* )
;并且根据您的内存配置,其中一些数据可能不会被缓存,必须从磁盘读取。)
一个解决方案是在索引中包含所有使用的列(“覆盖索引”),例如在 date, 01
上创建索引。那么 MySQL 就不需要访问表本身,可以像第一种方法一样,只读索引就可以继续。索引的大小会增加一点,因此 MySQL 将需要读取“更多 MB”(并执行 avg
操作),但这仍然是几秒钟的事情。
在评论中,您提到您需要计算 24 列的平均值。如果你想同时计算多个列的 avg
,你需要对所有列都使用一个覆盖索引,例如date, 01, 02, ..., 24
以防止访问表。请注意,包含所有列的索引需要与表本身一样多的存储空间(并且创建这样的索引需要很长时间),因此它可能取决于此查询的重要性是否值得这些资源。
为了避免MySQL-limit of 16 columns per index ,您可以将其拆分为两个索引(和两个查询)。创建例如索引 date, 01, .., 12
和 date, 13, .., 24
,然后使用
select * from (select `date`, avg(`01`), ..., avg(`12`)
from mytable where `date` = ...) as part1
cross join (select avg(`13`), ..., avg(`24`)
from mytable where `date` = ...) as part2;
确保记录好这一点,因为没有明显的理由以这种方式编写查询,但它可能是值得的。
如果您只对单个列进行平均,则可以添加 24 个单独的索引(在 date, 01
, date, 02
, ...),尽管在总的来说,它们将需要更多的空间,但可能会快一点(因为它们单独较小)。但是缓冲池可能仍然倾向于完整索引,具体取决于使用模式和内存配置等因素,因此您可能需要对其进行测试。
由于 date
是主键的一部分,您还可以考虑将主键更改为 date, esi
。如果您通过主键查找日期,则不需要额外的步骤来访问表数据(因为您已经访问了表),因此行为类似于覆盖索引。但这是对您的表的重大更改,可能会影响所有其他查询(例如使用 esi
来定位行),因此必须仔细考虑。
正如您所提到的,另一种选择是构建一个汇总表,您可以在其中存储预先计算的值,特别是如果您不添加或修改过去日期的行(或者可以使用触发器使它们保持最新)。
关于mysql - MySQL 服务器上非常简单的 AVG() 聚合查询需要很长时间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49397333/
目前我正在构建相当大的网络系统,我需要强大的 SQL 数据库解决方案。我选择 Mysql 而不是 Postgres,因为一些任务需要只读(MyISAM 引擎)而其他任务需要大量写入(InnoDB)。
我在 mysql 中使用如下命令。当它显示表格数据时,它被格式化为一个非常干净的表格,间距均匀且 |作为列分隔符。 SELECT * FROM TABLE_NAME; 当我从 CLI 运行命令时,如下
我知道这个问题之前已经被问过好几次了,我已经解决了很多问题,但到目前为止没有任何效果。 MySQL 试图将自身安装到的目录 (usr/local/mysql) 肯定有问题。关于我的错误的奇怪之处在于我
以下是我的 SQL 数据结构,我正在尝试如下两个查询: Select Wrk_ID, Wrk_LastName, Skill_Desc from Worker, Skill where
我们有一个本地 mysql 服务器(不在公共(public)域上),并希望将该服务器复制到我们拥有的 google 云 sql 实例。我的问题是:1.这可能吗?2.我们的本地服务器只能在本地网络上访问
我有一个表(test_table),其中一些字段值(例如字段 A、B 和 C)是从外部应用程序插入的,还有一个字段(字段 D),我想从现有表(store_table)插入其值,但在插入前者(A、B 和
我想创建一个 AWS RDS 实例,然后使用 terraform 管理数据库用户。因此,首先,我创建了一个 RDS 实例,然后使用创建的 RDS 实例初始化 mysql 提供程序,以进一步将其用于用户
当用户在我的网站上注册时,他们会在我的一个数据库中创建自己的表格。该表存储用户发布的所有帖子。我还想做的是也为他们生成自己的 MySql 用户——该用户仅有权从他们的表中读取、写入和删除。 创建它应该
我有一个关于 ColdFusion 和 Mysql 的问题。我有两个表:PRODUCT 和 PRODUCT_CAT。我想列出包含一些标记为:IS_EXTRANET=1 的特殊产品的类别。所以我写了这个
我想获取 recipes_id 列的值,以获取包含 ingredient_id 的 2,17 和 26 条目的值。 假设 ingredient_id 2 丢失则不获取记录。 我已经尝试过 IN 运算符
在 Ubuntu 中,我通常安装两者,但 MySQL 的客户端和服务器之间有什么区别。 作为奖励,当一个新语句提到它需要 MySQL 5.x 时,它是指客户端、服务器还是两者兼而有之。例如这个链接ht
我重新访问了我的数据库并注意到我有一些 INT 类型的主键。 这还不够独特,所以我想我会有一个指导。 我来自微软 sql 背景,在 ssms 中你可以 选择类型为“uniqeidentifier”并自
我的系统上有 MySQL,我正在尝试确定它是 Oracle MySQL 还是 MySQL。 Oracle MySQL 有区别吗: http://www.oracle.com/us/products/m
我是在生产 MySQL 中运行的应用程序的新维护者。之前的维护者已经离开,留下的文档很少,而且联系不上了。 我面临的问题是执行以下请求大约需要 10 秒: SELECT COUNT(*) FROM `
我有两个位于不同机器上的 MySQL 数据库。我想自动将数据从一台服务器传输到另一台服务器。比方说,我希望每天早上 4:00 进行数据传输。 可以吗?是否有任何 MySQL 内置功能可以让我们做到这一
有什么方法可以使用 jdbc 查询位于 mysql 根目录之外的目录中的 mysql 表,还是必须将它们移动到 mysql 根目录内的数据库文件夹中?我在 Google 上搜索时没有找到任何东西。 最
我在 mysql 数据库中有两个表。成员和 ClassNumbers。两个表都有一个付费年份字段,都有一个代码字段。我想用代码数字表中的值更新成员表中的付费年份,其中成员中的代码与 ClassNumb
情况:我有 2 台服务器,其中一台当前托管一个实时 WordPress 站点,我希望能够将该站点转移到另一台服务器,以防第一台服务器出现故障。传输源文件很容易;传输数据库是我需要弄清楚如何做的。两台服
Phpmyadmin 有一个功能是“复制数据库到”..有没有mysql查询来写这个函数?类似于将 db A 复制到新的 db B。 最佳答案 首先创建复制数据库: CREATE DATABASE du
我有一个使用 mySQL 作为后端的库存软件。我已经在我的计算机上对其进行了测试,并且运行良好。 当我在计算机上安装我的软件时,我必须执行以下步骤: 安装 mySQL 服务器 将用户名指定为“root
我是一名优秀的程序员,十分优秀!