将字符集设置为utf8mb4会使查询非常缓慢

问题描述 投票:0回答:1

我已经调试了好几个小时,非常感谢您提供帮助,以查看是否遗漏了非常明显的内容。我有一个具有30k行的MySQL表。架构如下:

CREATE TABLE `log` (
  `ip` varchar(15) COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `date` int(11) NOT NULL,
  `requested` mediumtext COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `response` mediumtext COLLATE utf8mb4_unicode_520_ci NOT NULL,
  `id` bigint(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci;

索引是:

ALTER TABLE `logs`
  ADD PRIMARY KEY (`id`) USING BTREE,
  ADD KEY `date` (`date`);

在phpmyadmin中,当我查询SELECT ip, date, requested FROM log ORDER BY date DESC LIMIT 0, 1000时,查询需要花费几毫秒。但是,在我的PHP代码中,当我执行相同的查询时:

$mysqli = new mysqli(...);

$s = microtime(true);
$mysqli->set_charset('utf8mb4');
$query = $mysqli->prepare('SELECT ip, date, requested FROM log ORDER BY date DESC LIMIT 0, 1000');
$query->execute();
$query->bind_result($ip, $date, $requested);
while($query->fetch()) {
  // ... just echoing the results
}

$e = microtime(true);
echo $e - $s;

需要6到7秒。列id是主键,索引设置为PRIMARYdate

一些观察和调试步骤:

  • 如果我移除set_charset,则需要1.5秒。

  • 如果我保留utf8mb4字符集,但仅选择ipdate,查询将在〜0.002秒内完成。

  • 我在网上搜索解决方案,例如this solution没有任何区别。

  • EXPLAIN表示possible_keysnull,这很奇怪,因为似乎date应该用作索引。即使FORCE INDEX也不使用索引。

  • 在我将排序规则更改为utf8mb4_unicode_520_ci之前,它工作得很好-以前是utf8_unicode。

我想念的是什么?我如何才能将此查询加速到合理的水平?提前非常感谢您!! :)

php mysql query-performance
1个回答
0
投票
SELECT ip, date, requested FROM log
    ORDER BY date DESC LIMIT 0, 1000

需要INDEX(date)

如果要从一个ip中获取最新的20个,

SELECT ip, date, requested FROM log
    WHERE ip = '11.22.33.44'
    ORDER BY date DESC LIMIT 0, 20

需要INDEX(IP, date)

如果ip是IP地址,则ascii就足够了。这只会比utf8mb4快一点。字符集是导致速度下降的原因。缺少索引是。速度下降的另一个原因是铲起1000个笨重的(?)行。

A

可能

速度下降和时序变化较大的原因是innodb_buffer_pool_size的值。buffer_pool太小而无法保存数据;它会击中磁盘。你有多少RAM?应将buffer_pool_size设置为available RAM的大约70%。为什么dateINT?请参见数据类型DATETIMEDATETIMESTAMP

请提供EXPLAIN;您说的某些话彼此不同。并执行EXPLAIN FORMAT=JSON SELECT ...了解更多信息。 (如果该格式不可用,那么该升级您的MySQL版本了。)

您是否忽略IPv6的存在?

© www.soinside.com 2019 - 2024. All rights reserved.