1

表结构:

CREATE TABLE `mytable` (
  `id` varchar(8) NOT NULL,
  `event` varchar(32) NOT NULL,
  `event_date` date NOT NULL,
  `event_time` time NOT NULL,
  KEY `id` (`id`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8

此表中的数据如下所示:

 id      | event      | event_date  | event_time
---------+------------+-------------+-------------
ref1     | someevent1 | 2010-01-01  | 01:23:45
ref1     | someevent2 | 2010-01-01  | 02:34:54
ref1     | someevent3 | 2010-01-18  | 01:23:45
ref2     | someevent4 | 2012-10-05  | 22:23:21
ref2     | someevent5 | 2012-11-21  | 11:22:33

该表包含大约 500.000.000 条与此类似的记录。

我想在这里询问的查询如下所示:

SELECT     *
FROM       `mytable`
WHERE      `id` = 'ref1'
ORDER BY   event_date DESC,
           event_time DESC
LIMIT      0, 500

EXPLAIN输出如下所示:

select_type:   SIMPLE
table:         E
type:          ref
possible_keys: id
key:           id
key_len:       27
ref:           const     
rows:          17024 (a common example)
Extra:         Using where; Using filesort

目的:此查询由网站生成,LIMIT-values 用于页面导航元素,因此如果用户想要查看较旧的条目,他们将被调整为500, 500,然后1000, 500等等。

由于字段中的某些项目id可以设置在相当多的行中,因此越来越多的行当然会导致查询速度变慢。分析那些缓慢的查询向我展示了排序的原因,在查询过程中,mysql 服务器大部分时间都在忙于对数据进行排序。索引字段event_dateevent_time没有太大变化。

示例SHOW PROFILE结果,按持续时间排序:

state          | duration/sec | percentage
---------------|--------------|-----------
Sorting result |     12.00145 |   99.80640
Sending data   |      0.01978 |    0.16449
statistics     |      0.00289 |    0.02403
freeing items  |      0.00028 |    0.00233
...
Total          |     12.02473 |  100.00000

现在的问题:

在深入研究 mysql 变量之类的sort_buffer_size其他服务器配置选项之前,您能想出任何方法来更改查询或排序行为,因此排序不再是那么大的性能消耗者,并且该查询的目的仍然存在吗?

我不介意一些开箱即用的想法。

先感谢您!

4

3 回答 3

2

正如我在评论中所写的那样,多列索引(id、evet_date desc、event_time desc)可能会有所帮助。

如果此表将快速增长,您应该考虑在应用程序中添加选项,以便用户选择特定日期范围的数据。

示例:第一步总是返回 500 条记录,但要选择下一条记录,用户应设置数据的日期范围,然后设置分页。

于 2012-11-09T13:37:40.450 回答
1

索引很可能是解决方案;你只需要做对。请参阅mysql 参考页面

最有效的方法是在(id, event_date, event_time). 您可以event_date desc, event_time desc在索引中指定,但我认为没有必要。

于 2012-11-09T13:32:43.243 回答
1

我会先做 sufleR 建议的事情 - (id, event_date desc, event_time desc) 上的多列索引。

但是,根据http://dev.mysql.com/doc/refman/5.0/en/create-index.html,支持 DESC 关键字,但实际上并没有做任何事情。这有点痛苦——所以尝试一下,看看它是否能提高性能,但可能不会。

如果是这种情况,你可能不得不通过创建一个“sort_column”来作弊,它的值会自动递减(很确定你必须在应用层这样做,我认为你不能在 MySQL 中递减),并且将该列添加到索引中。

你最终会得到:

id      | event      | event_date  | event_time  | sort_value
---------+------------+-------------+-------------------------
ref1     | someevent1 | 2010-01-01  | 01:23:45   | 0
ref1     | someevent2 | 2010-01-01  | 02:34:54   | -1
ref1     | someevent3 | 2010-01-18  | 01:23:45   | -2
ref2     | someevent4 | 2012-10-05  | 22:23:21   | -3
ref2     | someevent5 | 2012-11-21  | 11:22:33   | -4

以及 ID 和 sort_value 上的索引。

很脏,但唯一的其他建议是以其他方式减少与 where 子句匹配的记录数 - 例如,通过更改接口不返回 500 条记录,而是返回给定日期的记录。

于 2012-11-09T13:34:09.877 回答