Mysql 数据库性能检查表
在数据库中,我有一个带有订单项的表。该表包含大约3600万条记录 运行这样的查询大约需要3分钟:Mysql 数据库性能检查表,mysql,database,performance,database-performance,Mysql,Database,Performance,Database Performance,在数据库中,我有一个带有订单项的表。该表包含大约3600万条记录 运行这样的查询大约需要3分钟: SELECT COUNT(DISTINCT DATE(created_on), product_id) FROM order_items; SELECT COUNT(1) FROM order_items; 运行这样的查询大约需要13秒: SELECT COUNT(DISTINCT DATE(created_on), product_id) FROM order_items; SELECT C
SELECT COUNT(DISTINCT DATE(created_on), product_id) FROM order_items;
SELECT COUNT(1) FROM order_items;
运行这样的查询大约需要13秒:
SELECT COUNT(DISTINCT DATE(created_on), product_id) FROM order_items;
SELECT COUNT(1) FROM order_items;
有些东西告诉我3600万条记录并不多,而且两个查询都运行得相当慢
在这里开始调查绩效问题的检查表是什么?
我们使用的是MySQL(实际上是它的Clustrix版本,MySQL 5.0.45-Clustrix-6.0.1
)
编辑。添加更多信息:
/* SHOW CREATE TABLE order_items; */
CREATE TABLE `order_items` (
`id` int(10) unsigned not null AUTO_INCREMENT,
`state` enum('pending','sold_out','approved','declined','cancelled','processing','completed','expired') CHARACTER SET utf8 not null default 'pending',
`order_id` int(10) unsigned not null,
`product_id` int(10) unsigned not null,
`quantity` smallint(5) unsigned not null,
`price` decimal(10,2) unsigned not null,
`total` decimal(10,2) unsigned not null,
`created_on` datetime not null,
`updated_on` datetime not null,
`employee_id` int(11),
`customer_id` int(11) unsigned not null,
PRIMARY KEY (`id`) /*$ DISTRIBUTE=1 */,
KEY `updated_on` (`updated_on`) /*$ DISTRIBUTE=1 */,
KEY `state` (`state`,`quantity`) /*$ DISTRIBUTE=3 */,
KEY `product_id` (`product_id`,`state`) /*$ DISTRIBUTE=2 */,
KEY `product` (`product_id`) /*$ DISTRIBUTE=1 */,
KEY `order_items_quantity` (`quantity`) /*$ DISTRIBUTE=2 */,
KEY `order_id` (`order_id`,`state`,`created_on`) /*$ DISTRIBUTE=3 */,
KEY `order` (`order_id`) /*$ DISTRIBUTE=1 */,
KEY `index_order_items_on_employee_id` (`employee_id`) /*$ DISTRIBUTE=2 */,
KEY `customer_id` (`customer_id`) /*$ DISTRIBUTE=2 */,
KEY `created_at` (`created_on`) /*$ DISTRIBUTE=1 */,
) AUTO_INCREMENT=36943352 CHARACTER SET utf8 ENGINE=InnoDB /*$ REPLICAS=2 SLICES=12 */
以及:
编辑2。以下是两个查询的解释语句:
mysql> EXPLAIN SELECT COUNT(1) FROM order_items;
+----------------------------------------------------------+-------------+-------------+
| Operation | Est. Cost | Est. Rows |
+----------------------------------------------------------+-------------+-------------+
| row_count "expr1" | 29740566.81 | 1.00 |
| stream_combine | 26444732.70 | 32958341.10 |
| compute expr0 := param(0) | 1929074.80 | 2746528.43 |
| filter isnotnull(param(0)) | 1915342.16 | 2746528.43 |
| index_scan 1 := order_items.order_items_quantity | 1854308.19 | 3051698.25 |
+----------------------------------------------------------+-------------+-------------+
5 rows in set (0.13 sec)
以及:
第一个查询必须遍历整个数据库,检查表中的每一行。在created_on和product_id上建立索引可能会显著加快速度。如果您不了解索引,那么这是一个很好的起点
第二个查询在我看来应该是即时的,因为它只需要检查表元数据,不需要检查任何行。需要注意的一些事情:
- 如果添加
索引(product\u id,created\u on)
,第一个查询应该运行得更快,因为它将是一个“覆盖索引”。(字段的顺序可以相反。)
- 按照给定的顺序运行这两个查询可能会导致缓存信息,从而使第二个查询运行得更快
从tbl中选择COUNT(*)
将使用最小的索引。(在InnoDB中)
- 如果您有足够的RAM,并且
innodb\u buffer\u pool\u size
大于该表,则一个或另一个操作可能完全在RAM中执行。RAM比磁盘快得多
请提供SHOW CREATE TABLE order\u项目代码>我猜得太多了。
请提供显示变量,如“%buffer%”代码>。你有多少公羊
编辑
由于是Clustrix,可能会发生完全不同的事情。这里有一个猜测:
选择计数(1).
可能会分发到节点;每个节点将得到一个小计;然后可以(非常迅速地)添加小计
选择COUNT(DISTINCT…。
必须以某种方式查看所有行。也就是说,这种努力是无法分配的。可能发生的情况是,所有行都被铲到一个节点进行处理。我猜这是几GB的东西
在Clustrix中是否有办法获得解释?我很想看看它对每个选项的说明。(以及它是否支持我的猜测。)
我认为groupby
和DISTINCT
在“分片”系统(如Clustrix)中效率很低。您应该发布查询计划,但我怀疑要处理查询,MySQL必须遍历产品id和创建的索引。对于created_on字段,它还必须聚合值(该字段为datetime,但您希望按日期分组)。如果您需要速度,我将添加仅包含日期的created_on date字段,并在product_id和created_on date上创建索引。这将使您的查询速度更快。
当然,count(1)查询更快,因为它根本不读取表,并且可以使用索引元数据。
- 计数(1)
在计划中,使用了流式联合收割机。它只读取了索引(订单项\数量
(数量
)
- 计数(不同日期(创建日期),产品id)
一般来说,在RDB中计数(不同…)可能效率低下,而NewSQL扩展RDB的效率更高,这是因为难以减少节点间通信量(在许多情况下,大量数据应转发到GTM节点)。因此Clustrix需要“dist\u stream\u aggregate”和正确的索引(列和列顺序)
在平面图中,显示了hash\u aggregate\u partial。它扫描了整个表(\uuuiDx\uOrder\uItems\uuuuu PRIMARY
),花费了大量时间(大得多)
对于并行性,对于所有可用的CPU来说,它可能不够多。(即切片=12)。我想知道每个节点有多少个节点和CPU(?)
由于日期(created_on
),在
创建的索引(created_on
)将无法工作。优化器(Plan)认为完整表扫描比查找索引(在
处创建)和访问表(\uIdx\uOrder\uItems\uuuu PRIMARY
)更有效
对于这种情况,我建议进行如下测试
- 添加列
create\u on\u date\u type
- 在
订单项目上创建新索引(在日期上创建索引类型,产品ID
)
关于分配=?&切片=?,应该对数据集进行测试。(切片的数量可能会影响cpu并行性的工作程度)
- 您必须确保计划具有
dist\u stream\u aggregate
。
dist\u stream\u aggregate
只能有效地使用查询的“new\u index”列
我相信你会有更好的表现。嗯?否innodb\u缓冲区\u池\u大小
?(有一次我看到你有engine=InnoDB
,我就去找那个设置。)嗯。。。我对Clustrix的细节不太熟悉——也许他们会凌驾于InnoDB?Rick之上,谢谢你进一步的研究。我添加了两个EXPLAIN
语句。。。我假设在进行计数之前,stream\u combine
正在合并所有3300万行。这似乎非常低效,而且“容易”优化。此外,此查询的成本更高。然而,你的时间安排显示它要快得多。也许hash\u aggregate\u partial
和/或hash\u aggregate\u combine
的成本比Clustrix的成本模型想象的要高。建议您向Clustrix展示此线程。