MySQL:在最后一秒插入了某种类型的行数

时间:2014-11-01 08:51:35

标签: mysql sql query-optimization

我有两个mysql表ab,一对多关系(b实际上是a之间多对多关系的链接表{1}}和其他一些表格:

mysql> DESCRIBE a;
+-------+--------------+------+-----+-------------------+-----------------------------+
| Field | Type         | Null | Key | Default           | Extra                       |
+-------+--------------+------+-----+-------------------+-----------------------------+
| id    | bigint(30)   | NO   | PRI | 0                 |                             |
| date  | timestamp    | NO   | MUL | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
+-------+--------------+------+-----+-------------------+-----------------------------+
2 rows in set (0.00 sec)

mysql> DESCRIBE b;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| a_id  | bigint(30)  | NO   | PRI | 0       |       |
| field | smallint(6) | NO   | PRI | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)

随着频繁插入新行,我需要知道最后一秒在表b中插入了多少行。 我还需要区分b.field大于,等于或小于0的行({somedate}是一秒前的时间):

SELECT count(*) FROM a INNER JOIN b ON a.id = b.a_id
WHERE a.date >= '{somedate}' AND b.field > 0

SELECT count(*) FROM a INNER JOIN b ON a.id = b.a_id
WHERE a.date >= '{somedate}' AND b.field = 0

SELECT count(*) FROM a INNER JOIN b ON a.id = b.a_id
WHERE a.date >= '{somedate}' AND b.field < 0

这三个查询花了大约5秒钟,所以我尝试通过将它们全部放在同一个查询中来优化它们:

SELECT sum(CASE WHEN b.field > 0 THEN 1 ELSE 0 END),
    sum(CASE WHEN b.field = 0 THEN 1 ELSE 0 END),
    sum(CASE WHEN b.field < 0 THEN 1 ELSE 0 END)
FROM a INNER JOIN b ON a.id = b.a_id
WHERE a.date >= '{somedate}'

但是,我不确定这是否有所改善。

我的性能问题仅仅是因为我对最后一秒发生的事情感兴趣,所以如果查询占用的时间超过一秒,这显然不是很有用。

如何改善这些查询的效果?最好不必修改表格。

更多信息:

mysql> SHOW CREATE TABLE a\G
*************************** 1. row ***************************
       Table: a
Create Table: CREATE TABLE `a` (
  `id` bigint(30) NOT NULL DEFAULT '0',
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `date_index` (`date`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
1 row in set (0.00 sec)

mysql> SHOW CREATE TABLE b\G
*************************** 1. row ***************************
       Table: b
Create Table: CREATE TABLE `b` (
  `a_id` bigint(30) NOT NULL DEFAULT '0',
  `field` smallint(6) NOT NULL,
  PRIMARY KEY (`a_id`,`field`),
  KEY `a_id_fk` (`a_id`),
  KEY `field_fk` (`field`),
  CONSTRAINT `a_id_fk` FOREIGN KEY (`a_id`) REFERENCES `a` (`id`),
  CONSTRAINT `field_fk` FOREIGN KEY (`field`) REFERENCES `c` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
1 row in set (0.00 sec)   

mysql> EXPLAIN SELECT count(*) FROM a INNER JOIN b ON a.id = b.a_id WHERE a.date >= '2014-10-15' AND b.field = 0;
+----+-------------+-------+--------+--------------------------+----------+---------+-----------------+-------+-------------+
| id | select_type | table | type   | possible_keys            | key      | key_len | ref             | rows  | Extra       |
+----+-------------+-------+--------+--------------------------+----------+---------+-----------------+-------+-------------+
|  1 | SIMPLE      | b     | ref    | PRIMARY,field_fk,a_id_fk | field_fk | 2       | const           | 40698 | Using index |
|  1 | SIMPLE      | a     | eq_ref | PRIMARY                  | PRIMARY  | 8       | database.b.a_id |     1 | Using where |
+----+-------------+-------+--------+--------------------------+----------+---------+-----------------+-------+-------------+
2 rows in set (0.00 sec)

mysql> EXPLAIN SELECT count(*) FROM a INNER JOIN b ON a.id = b.a_id WHERE a.date >= '2014-10-15' AND b.field > 0;
+----+-------------+-------+--------+--------------------------+----------+---------+-----------------+--------+--------------------------+
| id | select_type | table | type   | possible_keys            | key      | key_len | ref             | rows   | Extra                    |
+----+-------------+-------+--------+--------------------------+----------+---------+-----------------+--------+--------------------------+
|  1 | SIMPLE      | b     | range  | PRIMARY,field_fk,a_id_fk | field_fk | 2       | NULL            | 370846 | Using where; Using index |
|  1 | SIMPLE      | a     | eq_ref | PRIMARY                  | PRIMARY  | 8       | database.b.a_id |      1 | Using where              |
+----+-------------+-------+--------+--------------------------+----------+---------+-----------------+--------+--------------------------+
2 rows in set (0.00 sec)

mysql> EXPLAIN SELECT sum(CASE WHEN b.field > 0 THEN 1 ELSE 0 END), sum(CASE WHEN b.field = 0 THEN 1 ELSE 0 END), sum(CASE WHEN b.field < 0 THEN 1 ELSE 0 END) FROM a INNER JOIN b ON a.id = b.a_id WHERE a.date >= '2014-10-15';
+----+-------------+-------+--------+-----------------+----------+---------+-----------------+--------+-------------+
| id | select_type | table | type   | possible_keys   | key      | key_len | ref             | rows   | Extra       |
+----+-------------+-------+--------+-----------------+----------+---------+-----------------+--------+-------------+
|  1 | SIMPLE      | b     | index  | PRIMARY,a_id_fk | field_fk | 2       | NULL            | 741976 | Using index |
|  1 | SIMPLE      | a     | eq_ref | PRIMARY         | PRIMARY  | 8       | database.b.a_id |      1 | Using where |
+----+-------------+-------+--------+-----------------+----------+---------+-----------------+--------+-------------+
2 rows in set (0.00 sec)

0 个答案:

没有答案