【发布时间】:2018-07-30 18:40:06
【问题描述】:
我有一个这样的 MySql 事件表:
+---------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+--------------+------+-----+---------+----------------+
| EventId | int(11) | NO | PRI | NULL | auto_increment |
| ControllerId | int(11) | NO | MUL | NULL | |
| EventTypeId | int(11) | NO | MUL | NULL | |
| DateTime | datetime(3) | NO | MUL | NULL | |
| InputId | int(11) | YES | MUL | | |
...
| AdditionalInfo | text | YES | | | |
+---------------------+--------------+------+-----+---------+----------------+
目前它有 200M 条记录,并且它一直在运行文件。为了保持速度,我不使用任何连接查询它,但现在我开始遇到一些长时间运行的查询。一个运行缓慢的查询示例如下:
SELECT E.*
FROM Event E
WHERE (E.EventTypeId != 4 OR (E.EventTypeId = 4 AND E.InputId IS NOT NULL))
AND E.EventTypeId != 27 AND E.EventTypeId != 12
AND E.ControllerId in (5190, 5191, 5192, 5193)
ORDER BY E.DateTime DESC
LIMIT 0, 200
该查询需要 5 分钟!解释的重要(我认为)部分如下所示:
"key_length": "7",
"rows_examined_per_scan": 180071,
"rows_produced_per_join": 125770,
"filtered": "0.06",
"cost_info": {
"read_cost": "284389.84",
"eval_cost": " 25154.17",
"prefix_cost": "309544.01",
"data_read_per_join": "20M"
},
现在,如果我在查询结束时删除ORDER BY E.DateTime DESC,大约需要 0.1 秒才能完成。我已经在 DateTime 上有一个索引。
我想我理解服务器必须读取所有 180k 的概念? WHERE 子句返回的行在返回给客户端之前对其进行排序,但为什么需要这么长时间?我能做些什么吗?复合索引在这里有用吗?
【问题讨论】:
-
那么数据库要遍历和排序的记录很多,尝试将您的限制缩小到更小的数量?!
-
查询是针对向用户显示的“最近事件”,它们有可选择的最近事件数量,最大为 200,默认为 20。我有 some 如果我取消了查看 200 个最近事件的选项,用户会大吃一惊。
-
这不是有点像
eventtypeid NOT IN(4,27,12) OR (...) -
是的,我没有考虑过-尽管答案中提到了,谢谢。已将其修改为
WHERE (E.EventTypeId != 4 OR (E.InputId IS NOT NULL)) AND E.EventTypeId NOT IN (12, 27)
标签: mysql sql performance select query-performance