数据库性能检查表

时间:2015-07-09 22:29:14

标签: mysql database performance database-performance

在数据库中,我有一个包含订单商品的表格。该表包含大约3600万条记录。

运行这样的查询需要 3分钟

SELECT COUNT(DISTINCT DATE(created_on), product_id) FROM order_items;

运行这样的查询需要 13秒

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 */

/* SHOW VARIABLES LIKE '%buffer%'; */
+----------------------------------------+-------+
| Variable_name                          | Value |
+----------------------------------------+-------+
| backup_compression_buffer_size_bytes   | 8192  |
| backup_read_buffer_size_bytes          | 8192  |
| backup_write_buffer_size_bytes         | 8192  |
| mysql_master_trx_buffer_kb             | 256   |
| mysql_slave_session_buffer_size_events | 100   |
| net_buffer_length                      | 16384 |
| replication_master_buffer_kb           | 65536 |
+----------------------------------------+-------+

编辑2 。这两个查询的EXPLAIN语句:

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)

mysql> EXPLAIN SELECT COUNT(DISTINCT DATE(created_on), product_id) FROM order_items;
+----------------------------------------------------------------------------------+-------------+------------+
| Operation                                                                        | Est. Cost   | Est. Rows  |
+----------------------------------------------------------------------------------+-------------+------------+
| hash_aggregate_combine expr1 := count(DISTINCT (0 . "expr0"),(1 . "product_id")) | 10115923.36 | 4577547.38 |
|   hash_aggregate_partial GROUPBY((0 . "expr0"), (1 . "product_id"))              |  3707357.04 | 4577547.38 |
|     compute expr0 := cast(1.created_on, date)                                    |  2166388.20 | 3051698.25 |
|       index_scan 1 := order_items.__idx_order_items__PRIMARY                     |  2151129.71 | 3051698.25 |
+----------------------------------------------------------------------------------+-------------+------------+
4 rows in set (0.24 sec)

4 个答案:

答案 0 :(得分:0)

第一个查询必须遍历整个数据库,检查表中的每一行。 created_on和product_id上的索引可能会显着加快速度。如果您不了解索引,http://use-the-index-luke.com是一个很好的起点。

在我看来,第二个查询应该是即时的,因为它只需检查表元数据而不需要检查任何行。

答案 1 :(得分:0)

有些注意事项:

  • 如果添加INDEX(product_id, created_on),第一个查询应该运行得更快,因为它将覆盖索引"。 (字段的顺序可以相反。)

  • 按照给定的顺序运行这两个查询可能会导致信息被缓存,从而使第二个查询运行得更快。

  • SELECT COUNT(*) FROM tbl将使用最小的索引。 (在InnoDB中。)

  • 如果你有足够的RAM,并且如果innodb_buffer_pool_size大于表,那么一个或另一个操作可能完全在RAM中执行。 RAM比磁盘快很多。

请提供SHOW CREATE TABLE order_items;我不得不猜太多 请提供SHOW VARIABLES LIKE '%buffer%';。你有多少RAM?

修改

既然它是Clustrix,那么可能会发生根本不同的事情。这是一个猜测:

  • SELECT COUNT(1) ...可能会分发到节点;每个节点都会得到一个小计;然后可以(非常迅速地)添加小计。
  • SELECT COUNT(DISTINCT ...)...实际上必须以某种方式查看所有行。也就是说,努力无法分配。 或许会发生的是所有行被铲到一个节点进行处理。我猜这是几GB的东西。

Clustrix有某种方法可以获得EXPLAIN吗?我很想知道每个SELECTs的内容。 (以及它是否支持我的猜测。)

我希望GROUP BYDISTINCT在分片'中效率低下系统(如Clustrix)。

答案 2 :(得分:0)

您应该发布查询计划,但我怀疑要处理查询MySQL必须遍历product_id和created_on索引。对于created_on字段,它还必须聚合值(字段是日期时间,但是你想按日期分组)。如果你需要速度,我会添加额外的字段created_on_date只有日期,我会在product_id上创建一个索引created_on_date。它应该使您的查询更快。 当然count(1)查询更快,因为它根本不读取表,它可以使用索引元数据。

答案 3 :(得分:0)

  • COUNT(1)

在Plan中,使用了stream_combine。它只读取了索引(order_items_quantityquantity))

  • COUNT(DISTINCT DATE(created_on),product_id)

一般来说,COUNT(DISTINCT ...)在RDB,NewSQL Scale-Out RDB中效率可能更低,这是因为难以减少节点间流量(在很多情况下应该将大量数据转发到GTM节点) )。所以Clustrix需要'dist_stream_aggregate'和正确的索引(列和列顺序)

在计划中,显示了hash_aggregate_partial。它扫描了FULL TABLE(__idx_order_items__PRIMARY)并花了很多时间(更大的尺寸) 对于并行性,它可能不足以满足所有可用的cpu。 (即SLICES = 12)。我想知道每个节点有多少节点和cpus(?)

由于DATE(created_on),索引created_atcreated_on)无效。优化器(Plan)认为FULL TABLE SCAN比查找INDEX(created_at)然后访问TABLE(__idx_order_items__PRIMARY)更有效。

对于这种情况,我建议按以下方式进行测试。

  • 添加列create_on_date_type
  • order_items上创建索引new_index(create_on_date_typeproductid) 关于分配=? &安培; slices = ?,应该对你的数据集进行测试。(切片的数量可能会影响cpu并行性的工作量)
  • 您必须确保该计划有dist_stream_aggregatedist_stream_aggregate只能使用查询的“new_index”列高效工作。

我相信你可以获得更好的表现。