mysql - 如何在按日期/unix 时间戳分组时优化查询?

标签 mysql optimization indexing

我不是很习惯MySQL,但我认为它可以比现在快得多。

这是我的表格:

CREATE TABLE `crashes` (
`id` int(11) NOT NULL AUTO_INCREMENT,
 `added_date` int(11) NOT NULL,
 `status` int(11) NOT NULL,
 `issue_id` varchar(32) NOT NULL,
 `report_id` text NOT NULL,
 `app_version_code` text NOT NULL,
 `app_version_name` text NOT NULL,
 `package_name` varchar(80) NOT NULL,
 `package_name_id` tinyint(4) NOT NULL,
 `file_path` text NOT NULL,
 `phone_model` text NOT NULL,
 `android_version` text NOT NULL,
 `build` text NOT NULL,
 `brand` text NOT NULL,
 `product` text NOT NULL,
 `total_mem_size` int(11) NOT NULL,
 `available_mem_size` int(11) NOT NULL,
 `custom_data` text NOT NULL,
 `stack_trace` text NOT NULL,
 `initial_configuration` text NOT NULL,
 `crash_configuration` text NOT NULL,
 `display` text NOT NULL,
 `user_comment` text NOT NULL,
 `user_app_start_date` text NOT NULL,
 `user_crash_date` text NOT NULL,
 `dumpsys_meminfo` text NOT NULL,
 `dropbox` text NOT NULL,
 `logcat` text NOT NULL,
 `eventslog` text NOT NULL,
 `radiolog` text NOT NULL,
 `is_silent` text NOT NULL,
 `device_id` text NOT NULL,
 `installation_id` text NOT NULL,
 `user_email` text NOT NULL,
 `device_features` text NOT NULL,
 `environment` text NOT NULL,
 `settings_system` text NOT NULL,
 `settings_secure` text NOT NULL,
 `shared_preferences` text NOT NULL,
 `application_log` text NOT NULL,
 `media_codec_list` text NOT NULL,
 `thread_details` text NOT NULL,
 `user_ip` text NOT NULL,
 PRIMARY KEY (`id`),
 KEY `package_name_id` (`package_name_id`)
) ENGINE=MyISAM AUTO_INCREMENT=202364 DEFAULT CHARSET=utf8

如您所见,它有 20 万行。我想检索 added_date 行(unix 时间戳,int(11)),以及当天的行数。

所以我选择日期、日期(如 Y-M-D)和计数:

SELECT date_format(from_unixtime(added_date), '%Y-%c-%d') as date, added_date, count(*) as nb_crashes FROM crashes WHERE package_name = 'net.bicou.redmine' GROUP BY date ORDER BY date ASC

太慢了!在我主机上的专用 mysql 服务器上将近 1.5 秒。

所以我想我可以稍微优化一下:我添加了一个 tinyint 的 package_name_id,每个 package_name 都是唯一的(我有 5 个不同的 package_name 200k 行的值)。我将其设为 INDEX,以便 MySQL 可以更快地浏览它。
结果:0.9 秒。这好多了,但仍然低于我预期的性能!

我该如何优化它?我想在每一行上创建日期,然后分组非常昂贵。但是我不知道如何才能让它更快......

编辑:

这是我更新表格的操作:

ALTER TABLE  `crashes` ADD  `temp` DATETIME NOT NULL
UPDATE crashes SET temp = FROM_UNIXTIME( added_date )
ALTER TABLE  `crashes` ADD INDEX (  `temp` )

这是更新后的查询:

SELECT added_date, count(*) as nb_crashes FROM crashes WHERE package_name_id=3 GROUP BY year(temp),month (temp),dayofmonth(temp) ORDER BY temp ASC

我的执行时间仍然只有一秒左右……我是不是做错了什么?

最佳答案

如果您需要以类似日期的方式查询该字段,则不应使用 unix 时间戳值。您应该使用日期、日期时间或时间戳字段类型。

为什么?

因为如果您想查询特定日期的结果或按日期对记录进行分组,您将始终必须使用 FROM_UNIXTIME() 才能执行此操作。如果您尝试将日期值用于排序、连接、过滤器、组等,此函数调用将阻止您使用任何类型的索引。除了使用正确的方法之外,您无法改进查询数据类型,然后为您将要用于排序、筛选、联接、分组等的字段编制索引。

确实,在数据库中使用 unix 时间戳似乎被缺乏经验的 PHP 开发人员激增,他们认为在 PHP 中使用这种格式的日期更容易(要么他们懒得将日期/日期时间数据库输出转换为 unix 时间戳在 PHP 中,或者他们还没有弄清楚如何使用 dateTime 和 dateInterval PHP 类来使在 PHP 中处理日期更容易)。

我的建议是现在改掉这个习惯,开始学习如何在 MySQL 中使用日期/日期时间字段。

我建议查看您的表 DDL 的另一件事是,您可能应该重新审视那里的文本字段的使用。这些情况中的大多数看起来更像是 varchar 字段。

关于mysql - 如何在按日期/unix 时间戳分组时优化查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18747884/

相关文章:

mysql - 如何解释 MySQL 分析器输出以调整外部 MySQL 服务器

r - 访问嵌套在 R 列表中的向量的倒数第二个元素

linux - 如何使用awk读取每n个字符而不是每行的文件?

python在groupby之后访问列

svn - 在 SVN 存储库中搜索 office 文档的工具

mysql - 使用 homebrew 安装 MySQL 是否包括 Workbench 和 GUI(是否首选安装 native )?

mysql - 在名称字段上进行 GROUP BY,选择 ID 最小的行

php - mysql 从表中获取行号,其中列值等于特定值

c# - 通过 C# 在 MySQL 中检查和创建 View

flash - 任何学习 FLASM(Flash 字节码)的好指南?