如何优化我的SQL查询

时间:2017-04-07 12:43:05

标签: mysql sql query-optimization

我有一个表user_notification。执行了一个执行

的cron命令
SELECT * FROM `user_notification` `t` WHERE `t`.`status`=2;

其中状态1 - Send_fail,2- Queue,3- Success(像这样。)

在表格中,大约有100K记录,这些记录每天都呈指数级增长。此查询花费了太多时间。有没有办法优化这个查询?

#Table structure for table `user_notification`

CREATE TABLE `user_notification` (
  `id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `notification_id` int(11) NOT NULL,
  `notification_title` varchar(256) NOT NULL,
  `notification_message` text NOT NULL,
  `status` int(1) NOT NULL,
  `created` int(11) NOT NULL,
  `updated` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

ALTER TABLE `user_notification`
  ADD PRIMARY KEY (`id`),
  ADD KEY `user_id` (`user_id`),
  ADD KEY `notification_id` (`notification_id`);
ALTER TABLE `user_notification`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=94322;
ALTER TABLE `user_notification`
  ADD CONSTRAINT `user_notification_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
  ADD CONSTRAINT `user_notification_ibfk_2` FOREIGN KEY (`notification_id`) REFERENCES `notification` (`id`);


# Query_time: 0.010663  Lock_time: 0.000045 Rows_sent: 0  Rows_examined: 17294
SET timestamp=1491527264;
SELECT * FROM `user_notification` `t` WHERE `t`.`status`=2;

4 个答案:

答案 0 :(得分:1)

正如其他人所提到的,在status列上创建索引应该会有所帮助。

听起来你经常会在一个越来越大的表中使用相对较小的行子集(即“排队”行)。您可能想要考虑将“排队”记录放在他们自己的表中,然后将它们的状态更改为“成功”或“失败”时将它们移动到历史记录表中。这样,你只是从一张相对较小的桌子查询。当然,此策略涉及额外的删除和插入,因此可能会导致其他问题,具体取决于应用程序的工作方式。

答案 1 :(得分:0)

您的查询仅在0.01秒内执行,这非常快。如果你想要优化它,你可以做几件事。首先,您每次都需要所有8列吗?而不是使用

SELECT  *
FROM    user_notification t
WHERE   t.status=2;

您应该始终只列出您实际需要的字段:

SELECT  user_id, notification_id, notification_title, notification_message, status /*change columns as needed*/
FROM    user_notification t
WHERE   t.status=2;

除此之外,您可以为列状态创建索引以加快查询过滤。

ALTER TABLE user_notification 
CREATE NONCLUSTERED INDEX i1 ON user_notification (status);

答案 2 :(得分:0)

在列status上创建索引可以解决您的问题。

答案 3 :(得分:0)

"不要排队,只需这样做。"

认为MySQL是一个很好的排队系统是一个常见的错误。

如果排队和出列项目的麻烦近似于简单地执行任务的努力,那么就这样做。

好的,好的,你坚持排队吗?然后要么像杰拉德所说的那样做。或者也许只是有一个额外的桌子上的东西"等待完成"。

在轮询某些事情时,请务必注意事务性问题 - 否则两个线程可能会抓取并处理同一项目。

为什么在慢速日志中显示0.01s查询?可能你打开了log_queries_not_using_indexes。 (我发现这个设置实际上没用,只是在慢速日志中混乱。)