【问题标题】:Struggling to create correct index for simple sorted range query努力为简单的排序范围查询创建正确的索引
【发布时间】:2023-04-10 07:56:01
【问题描述】:

在我的数据库中,我有一个表“karmalog”。它基本上是系统中的操作日志。它包含几百行。我想检索最新的 36 个日志项,但只检索那些与一系列日志类型(称为“事件”)匹配的日志项。

这是查询:

 SELECT id
FROM karmalog
WHERE event
IN (
'FAV_IMG_ADD', 'FOLLOW', 'COM_POST', 'IMG_VOTE', 'LIST_VOTE', 'JOIN', 'CLASS_UP', 'LIST_CREATE', 'FORUM_REPLY', 'FORUM_CREATE', 'FORUM_SUBSCRIBE', 'IMG_GEO', 'IMG_ADDSPECIE', 'SPECIE_ADDVIDEO', 'EARN_MEDAL'
)
ORDER BY id DESC
LIMIT 0 , 36 

此查询当前需要 0.2 - 0.5 秒。我想让它进入 0.00x 范围。由于上述查询检索单个列、单个条件和单个排序参数,我想我只需创建一个适当的索引,一切都会好起来的。到目前为止没有运气。这是表定义,从不相关的字段中剥离:

DROP TABLE IF EXISTS `karmalog`;
CREATE TABLE `karmalog` (
  `id` int(11) NOT NULL auto_increment,
  `event` enum('EDIT_PROFILE','EDIT_AVATAR','EDIT_EMAIL','EDIT_PASSWORD','FAV_IMG_ADD','FAV_IMG_ADDED','FAV_IMG_REMOVE','FAV_IMG_REMOVED','FOLLOW','FOLLOWED','UNFOLLOW','UNFOLLOWED','COM_POSTED','COM_POST','COM_VOTE','COM_VOTED','IMG_VOTED','IMG_UPLOAD','LIST_CREATE','LIST_DELETE','LIST_ADMINDELETE','LIST_VOTE','LIST_VOTED','IMG_UPD','IMG_RESTORE','IMG_UPD_LIC','IMG_UPD_MOD','IMG_UPD_MODERATED','IMG_VOTE','IMG_VOTED','TAG_FAV_ADD','CLASS_DOWN','CLASS_UP','IMG_DELETE','IMG_ADMINDELETE','IMG_ADMINDELETEFAV','SET_PASSWORD','IMG_RESTORED','IMG_VIEW','FORUM_CREATE','FORUM_DELETE','FORUM_ADMINDELETE','FORUM_REPLY','FORUM_DELETEREPLY','FORUM_ADMINDELETEREPLY','FORUM_SUBSCRIBE','FORUM_UNSUBSCRIBE','TAG_INFO_EDITED','JOIN','IMG_GEO','IMG_ADDSPECIE','IMG_REMOVESPECIE','SPECIE_ADDVIDEO','SPECIE_REMOVEVIDEO','EARN_MEDAL') NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `user_id` (`user_id`),
  KEY `user_sec_id` (`user_sec_id`),
  KEY `image_id` (`object_id`),
  KEY `date_event` (`date_created`,`event`),
  KEY `event` (`event`),
  KEY `date_created` (`date_created`),
  KEY `date_created_2` (`date_created`,`id`),
  KEY `event_2` (`event`,`delete`),
  CONSTRAINT `user_id` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE SET NULL,
  CONSTRAINT `user_sec_id` FOREIGN KEY (`user_sec_id`) REFERENCES `user` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

如您所见,我已经尝试了一些索引。此版本中未显示其他两次索引尝试(id、事件和事件、id),均无济于事。在迄今为止尝试的所有组合中,MySQL 解释一直说它正在使用文件排序。

有什么想法吗?

【问题讨论】:

  • 我知道枚举映射到整数(或短整数),但我会尝试使用数值来代替。以防万一。
  • @leo 我将把它作为最后的手段,因为尝试这样做意味着重写应用程序的主要部分。这不是我可以快速尝试的。
  • 我不确定,但假设您有一个包含 30 个枚举的列表,并且您只想过滤其中的 10 个。如果您“巧妙地”将这 10 个与值 0~10 相关联,则可以使用“in between”子句(甚至
  • 我打赌mysql会按顺序分配下一个枚举值。在这种情况下,只需尝试按照您在查询中声明的顺序声明您的枚举(我的意思是,在创建表时首先声明在 WHERE 中使用的那些),然后让我们看看优化器是否足够聪明:-)

标签: mysql query-performance database-indexes


【解决方案1】:

这是您的查询:

SELECT id
FROM karmalog
WHERE event IN ('FAV_IMG_ADD', 'FOLLOW', 'COM_POST', 'IMG_VOTE', 'LIST_VOTE', 'JOIN',
                'CLASS_UP', 'LIST_CREATE', 'FORUM_REPLY', 'FORUM_CREATE', 'FORUM_SUBSCRIBE',   
                'IMG_GEO', 'IMG_ADDSPECIE', 'SPECIE_ADDVIDEO', 'EARN_MEDAL'
               )
ORDER BY id DESC
LIMIT 0 , 36;

第一个尝试的索引是karmalog(event, id)。第二个是karmalog(id, event)。这些都不在您的列表中。

【讨论】:

  • 正如问题所说“此版本中未显示其他两个索引尝试(id,事件和事件,id),均无济于事。”
猜你喜欢
  • 2016-12-17
  • 1970-01-01
  • 2020-01-06
  • 1970-01-01
  • 2012-02-23
  • 1970-01-01
  • 2021-07-21
  • 2011-08-21
  • 2021-11-07
相关资源
最近更新 更多