【问题标题】:Mysql Creating sort index performance for simple frequent queryMysql为简单的频繁查询创建排序索引性能
【发布时间】:2016-12-17 02:00:20
【问题描述】:

我正在处理一个包含大约 400 万条消息条目的 mysql 表,并且我正在尝试根据时间戳选择最新的 50 条消息。

另一个要求是返回的消息不以固定前缀开头。

问题是单个查询占用大约 25% 的 cpu,大约需要 1.5 秒。该查询由多个客户端频繁执行,导致我们的 8 核 db-server 出现性能问题。

SELECT * FROM largeTable 
WHERE msg NOT LIKE 'myPrefix%' 
ORDER BY timestamp DESC LIMIT 0, 50;

我尝试使用内置的 mysql 分析器进行分析,这是查询的结果:

+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000044 |
| checking permissions | 0.000004 |
| Opening tables       | 0.000010 |
| init                 | 0.000019 |
| System lock          | 0.000005 |
| optimizing           | 0.000005 |
| statistics           | 0.000007 |
| preparing            | 0.000007 |
| Sorting result       | 0.000002 |
| executing            | 0.000002 |
| Sending data         | 0.000006 |
| Creating sort index  | 0.788023 |
| end                  | 0.000009 |
| query end            | 0.000003 |
| closing tables       | 0.000009 |
| freeing items        | 0.000012 |
| cleaning up          | 0.000010 |
+----------------------+----------+

我首先想到的问题可能是它会检查所有条目的前缀,但在分析之后。

| Creating sort index  | 0.788023 |

似乎是罪魁祸首。那么 ORDER BY 条款呢? 我怎样才能加快速度? 我可以建立某种类型的索引来解决这个问题吗? 新消息大约每隔几秒就会添加一次,而查询的发生频率更高。

感谢您的帮助!

编辑:感谢 cmets,这是要求的信息。

数据库不是由我的代码创建和填充的,而是由一些外部 python 服务创建和填充的。我还没有添加任何索引。

解释输出:

id:1    
select_type:SIMPLE  
table:largeTable 
type:ALL    
possible_keys:NULL  
key: NULL   
key_len:NULL    
ref: NULL   
rows: 3492633   
Extra: Using where; Using filesort

表结构:

 CREATE TABLE `largeTable` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `timestamp` int(10) unsigned NOT NULL,
  `client_id` int(11) unsigned NOT NULL,
  `name` varchar(32) NOT NULL,
  `msg` varchar(528) NOT NULL,
  `target_id` int(11) unsigned DEFAULT NULL,
  `target_name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `client` (`client_id`)
) ENGINE=MyISAM AUTO_INCREMENT=4013829 DEFAULT CHARSET=utf8 |

【问题讨论】:

  • 您的msg 列上有索引吗?或者有什么索引?
  • 缺少信息:EXPLAIN 的输出,SHOW CREATE TABLE 的输出,使用哪个引擎以及是否使用 InnoDB - 配置。像往常一样,这很可能是由 innod_buffer_pool_size 设置不足引起的 I/O 问题。默认值是128mb,你应该提高它。
  • show create table largeTable 并发布。顺便说一句,核心数量无关紧要。 mysql 上的 smp 不确定
  • 考虑 在 (msg,timestamp) 上放置一个复合索引,并考虑这可能会减慢其他内容的速度。如果你已经在msg 上有一个索引(大概是宽的),添加一个 thin 时间戳并放弃另一个索引不会太痛苦
  • @RyanVincent 相关,谁知道stackoverflow.com/a/12033130

标签: php mysql sql myisam


【解决方案1】:

EXPLAINCREATE TABLE 表示您没有用于优化WHERE 子句的索引。这发生在ORDER BY 之前。所以让我们先关注索引。

ALTER TABLE largeTable
    ADD INDEX(msg);

但是,由于两件事,这不起作用:

`msg` varchar(528) NOT NULL,
ENGINE=MyISAM

您需要 528 个字符吗?如果你能把它降低到 255,那就行了。 (或者对于 MyISAM 可能是 341。)

您运行的是什么版本的 MySQL? 5.7 允许 528+utf8 作为索引。 5.6 也可以,但你必须做一些步骤才能让它成为可能。

【讨论】:

    猜你喜欢
    • 2023-04-10
    • 2012-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 2015-07-12
    • 2010-10-29
    相关资源
    最近更新 更多