我第一次在页面加载时运行这个查询,它总是需要大约 100 毫秒,即使它应该需要大约 1 毫秒。我已经通过 MySQL 控制台和 PhpMyAdmin 运行了完全相同的查询,而且它总是很快。
我在 PHP 中对它进行了计时,如下所示:
$t = microtime(true);
mysql_query($sql, $this->id);
die((microtime(true)-$t)*1000);
如果我第二次运行完全相同的查询(例如通过复制中间行),第二次几乎立即运行。
查询如下所示:
SELECT `user_id`, `login`, `first_name`, `last_name`, `name`, `email`, ... FROM `users` WHERE `user_id`='1000' LIMIT 1
通过实验我发现,如果我减少我选择的字段数量,它会突然跑得很快。当我添加第 26 列时,它从 1 毫秒跳到 100 毫秒。第 26 列是什么似乎无关紧要,即使是像“1”这样的常数,它也会突然变慢。
这可能是什么原因造成的,我该如何解决?
架构:
CREATE TABLE `user` (
`f1` int(11) unsigned NOT NULL DEFAULT '0',
`f2` varchar(50) NOT NULL DEFAULT '',
`f3` varchar(32) NOT NULL DEFAULT '',
`f4` varchar(50) DEFAULT NULL,
`f5` varchar(50) DEFAULT NULL,
`f6` varchar(100) NOT NULL DEFAULT 'Anonymous',
`f7` varchar(100) DEFAULT NULL,
`f8` varchar(100) NOT NULL DEFAULT 'Anonymous',
`f9` tinyint(1) NOT NULL DEFAULT '0',
`f10` tinyint(1) unsigned NOT NULL DEFAULT '0',
`f11` varchar(250) DEFAULT NULL,
`f12` int(10) unsigned NOT NULL DEFAULT '0',
`f13` varchar(250) NOT NULL DEFAULT '',
`f14` int(10) unsigned NOT NULL DEFAULT '0',
`f15` varchar(100) DEFAULT NULL,
`f16` varchar(25) DEFAULT NULL,
`f17` varchar(25) DEFAULT NULL,
`f18` varchar(25) DEFAULT NULL,
`f19` varchar(200) DEFAULT NULL,
`f20` varchar(50) DEFAULT NULL,
`f21` varchar(50) DEFAULT 'BC',
`f22` varchar(50) DEFAULT 'Canada',
`f23` varchar(20) DEFAULT NULL,
`f24` bigint(20) unsigned NOT NULL DEFAULT '0',
`f25` bigint(20) unsigned NOT NULL DEFAULT '0',
`f26` int(5) unsigned zerofill NOT NULL DEFAULT '00000',
`f27` tinyint(1) NOT NULL DEFAULT '0',
`f28` tinyint(1) unsigned NOT NULL DEFAULT '0',
`f29` tinyint(1) NOT NULL DEFAULT '0',
`f30` tinyint(1) unsigned NOT NULL DEFAULT '0',
`f31` varchar(50) DEFAULT NULL,
`f32` varchar(100) NOT NULL DEFAULT '',
`f33` bigint(20) unsigned NOT NULL DEFAULT '0',
`f34` bigint(20) unsigned NOT NULL DEFAULT '0',
`f35` varchar(250) DEFAULT NULL,
`f36` text NOT NULL,
`f37` tinyint(1) unsigned NOT NULL DEFAULT '0',
`f38` bigint(20) NOT NULL DEFAULT '0',
`f39` bigint(20) NOT NULL DEFAULT '0',
`f40` tinyint(1) unsigned NOT NULL DEFAULT '0',
`f41` tinyint(1) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`f1`),
UNIQUE KEY `f2` (`f2`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
我更改了字段名称以保护无辜者。
更新:我可能对魔法列限制有误。我认为这毕竟是一个字节限制......我尝试了所有数字,除了我实际需要的少数字段:
SELECT `f1`, `f2`, `f3`, `f4`, `f5`, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55 FROM `wx_user` WHERE `user_id`='1000' LIMIT 1
运行时间为 1 毫秒。如果我在末尾添加“56”,则需要约 100 毫秒。
我做了更多的测试:
mysql_query("SELECT 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' FROM `user` WHERE `f1`='1000' LIMIT 1");
在 1200 到 1300 a 之间的某个地方,它从 1 毫秒跳到 100 毫秒。
我可以使用更多列但更小的数据(整数)重复同样的事情。
这向我暗示了两件事:
- 它与发送的字节数有关
- 添加额外列的开销非常大,因为选择大约 50 个整数与选择单个 1300 个字符字段的效果相同。
现在我想起来,这个数字非常接近约翰建议的数字。1300 个字符 + 开销可能等于 John 提到的 1500 MTU 限制。
这是 MySQL 设置还是操作系统设置?我可以尝试什么?