我有两个模式相同的数据库。一个数据库来自生产,另一个是测试数据库。我正在对数据库中的一个表进行查询。在生产表上,查询大约需要4.3秒,而在测试数据库上,查询大约需要130毫秒。但是,生产表只有不到50000条记录,而我为测试表添加了超过100000条记录。我比较了这两个表,它们都有相同的索引。对我来说,问题似乎出在数据上。在播种时,我尝试生成尽可能随机的数据,以便模拟生产条件,但仍然无法重现缓慢的查询。
我查看了 EXPLAIN
对于这两个查询。它们在最后两栏中有显著差异。
生产:
+-------+-------------------------+
| rows | Extra |
+-------+-------------------------+
| 24459 | Using where |
| 46 | Using where; Not exists |
+-------+-------------------------+
测试:
+------+------------------------------------+
| rows | Extra |
+------+------------------------------------+
| 3158 | Using index condition; Using where |
| 20 | Using where; Not exists |
+------+------------------------------------+
生产表的create语句是:
CREATE TABLE `usage_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`operation` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
`check_time` datetime NOT NULL,
`check_in_log_id` int(11) DEFAULT NULL,
`daily_usage_id` int(11) DEFAULT NULL,
`duration_units` decimal(11,2) DEFAULT NULL,
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`facility_id` int(11) NOT NULL,
`notes` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`mac_address` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT '00:00:00:00:00:00',
`login` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_usage_logs_on_user_id` (`user_id`),
KEY `index_usage_logs_on_check_in_log_id` (`check_in_log_id`),
KEY `index_usage_logs_on_facility_id` (`facility_id`),
KEY `index_usage_logs_on_check_time` (`check_time`),
KEY `index_usage_logs_on_mac_address` (`mac_address`),
KEY `index_usage_logs_on_operation` (`operation`)
) ENGINE=InnoDB AUTO_INCREMENT=145147 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
而在测试数据库中相同的是:
CREATE TABLE `usage_logs` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`operation` varchar(30) COLLATE utf8_unicode_ci NOT NULL,
`check_time` datetime NOT NULL,
`check_in_log_id` int(11) DEFAULT NULL,
`daily_usage_id` int(11) DEFAULT NULL,
`duration_units` decimal(11,2) DEFAULT NULL,
`is_deleted` tinyint(1) NOT NULL DEFAULT '0',
`created_at` datetime DEFAULT NULL,
`updated_at` datetime DEFAULT NULL,
`facility_id` int(11) NOT NULL,
`notes` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
`mac_address` varchar(20) COLLATE utf8_unicode_ci NOT NULL DEFAULT '00:00:00:00:00:00',
`login` varchar(40) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `index_usage_logs_on_check_in_log_id` (`check_in_log_id`),
KEY `index_usage_logs_on_check_time` (`check_time`),
KEY `index_usage_logs_on_facility_id` (`facility_id`),
KEY `index_usage_logs_on_mac_address` (`mac_address`),
KEY `index_usage_logs_on_operation` (`operation`),
KEY `index_usage_logs_on_user_id` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=104001 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
完整查询是:
SELECT `usage_logs`.*
FROM `usage_logs`
LEFT OUTER JOIN usage_logs AS usage_logs_latest ON usage_logs.facility_id = usage_logs_latest.facility_id
AND usage_logs.user_id = usage_logs_latest.user_id
AND usage_logs.mac_address = usage_logs_latest.mac_address
AND usage_logs.check_time < usage_logs_latest.check_time
WHERE `usage_logs`.`facility_id` = 5
AND `usage_logs`.`operation` = 'checkIn'
AND (usage_logs.check_time >= '2018-06-08 00:00:00')
AND (usage_logs.check_time <= '2018-06-08 11:23:05')
AND (usage_logs_latest.id IS NULL)
我在同一台机器上对两个不同的数据库执行查询,所以我认为其他进程不会干扰结果。
这个结果意味着什么?我可以采取什么进一步的步骤来找出执行时间差异很大的原因?
1条答案
按热度按时间dl5txlt91#
您使用的mysql版本是什么?
有许多因素导致优化器决定
从哪张table开始(我们看不出它们是否不同)
要使用的索引(我们看不见)
等。
一些因素:
目前指数值的分布情况,
mysql版本,
月亮的相位。
这些也可能导致不同的数字(估计)在未来
EXPLAIN
,这可能导致不同的查询计划。此外,服务器中的其他活动可能会干扰cpu/io/etc的可用性。特别是数据缓存很容易显示10倍的差异。每个查询都运行了两次吗?查询缓存是否已关闭?是
innodb_buffer_pool_size
相同的?内存大小相同吗?我懂了
Using index condition
没有“综合”指数。通常可以通过提供合适的综合指数来改善绩效。更多我要看看这个问题!
播种
随机的,或者不是随机的,行可以影响优化器选择使用哪个索引(etc)。这可能会导致选择一种更好的方法来运行对“test”的查询。
我们得看看
EXPLAIN SELECT ...
进一步探讨这个Angular 。综合指数
这可能对两台服务器都有帮助:
进步很快。与其查找所有后面的行,但不使用它们的内容,不如使用“半联接”,它要求不存在任何这样的行:
(相同的索引就可以了。)
查询似乎得到了“除了最新的”;这就是你想要的吗?