MySQL - 为什么 phpMyAdmin 对于这个在 php/mysqli 中超级快的查询非常慢?

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

编辑:另请参阅我的答案,主要区别是phpmyadmin添加的

LIMIT
,但我仍然不明白,phpmyadmin仍然比mysqli慢。

在我们的数据库 (+web) 服务器上,在 phpmyadmin 中执行查询与从 php (mysqli) 或直接在 mariadb 服务器上执行查询时,性能存在巨大的差异。 60 秒 vs 这个查询功能非常好:< 0.01 seconds!

SELECT * FROM `TitelDaggegevens` WHERE `datum` > '2020-03-31' AND datum < '2020-05-02' AND `fondskosten` IS NULL ORDER BY isbn;

但是,

在phpMyAdmin中,当我们将2020-05-02更改为

2020-05-01
时,查询会变得非常慢。

SHOW PROCESSLIST

表明运行时查询主要是

Sending data

以下

mysql.rjweb.org/doc.php/index_cookbook_mysql#handler_counts

我做了以下查询系列: FLUSH STATUS; SELECT-query above with one of the two dates; SHOW SESSION STATUS LIKE 'Handler%';

差异令人着迷。 (我在所有情况下都忽略了等于 0 的所有值)。并且随着时间的推移保持一致。

| how: | server/MySqli | phpMyAdmin | date used in query: | 2020-05-02 | 2020-05-01 | 2020-05-02 | 2020-05-01 | records returned: | 6912 | 1 | 6912 | 1 | avg speed: | 0.27s | 0.00s | 0.52s | 60s (!) | Variable_name | Value | Value | Value | Value | Handler_icp_attempts | 213197 | 206286 | 213197 | 0 | Handler_icp_match | 6912 | 1 | 6912 | 0 | Handler_read_next | 6912 | 1 | 26651 | 11728896 (!) | Handler_read_key | 1 | 1 | 151 | 4 | Handler_commit | 1 | 1 | 152 | 5 | Handler_read_first | 0 | 0 | 1 | 1 | Handler_read_rnd_next | 0 | 0 | 82 | 83 | Handler_read_rnd | 0 | 0 | 0 | 1 | Handler_tmp_write | 0 | 0 | 67 | 67

在所有情况下 EXPLAIN 结果都是
相同

(phpmyadmin/mysqli/putty+mariadb)。 [select_type] => SIMPLE [table] => TitelDaggegevens [type] => range [possible_keys] => fondskosten,Datum+isbn+fondskosten [key] => Datum+isbn+fondskosten [key_len] => 3 [ref] => [Extra] => Using index condition; Using filesort

唯一的区别在于行:

[rows] => 422796 for 2020-05-01 [rows] => 450432 for 2020-05-02

问题

您能给我们任何

方向

,我们应该在哪里寻找解决这个问题的方法吗?我们花了一周的时间来优化 mariadb 服务器(现在是最佳状态,除了 phpmyadmin)并将我们的一些问题缩小到下面的示例。我们经常使用 phpmyadmin,但对底层的内容(例如它如何连接到数据库)几乎没有经验。

关于索引/排序

在慢速查询中,如果我们将

ORDER BY

从索引

isbn
字段更改为非索引字段,或者完全省略
ORDER BY
,一切都会再次恢复正常的闪电速度。将
ORDER BY
更改为主键
id
也会使其变慢,但仍然比索引
isbn
字段快 10 倍。

我们*知道*我们可以通过更好的索引来解决这个特定的查询,我们已经准备好实现这一点。但是,我们想知道是什么原因导致 phpmyadmin 与 mysqli/directly 中的时间不同。

详情:

TitelDaggegevens 包含

表结构:< 11mln records, not even 3Gb, and has been OPTIMIZEd (rebuild)

CREATE TABLE `TitelDaggegevens` ( `id` int(11) NOT NULL AUTO_INCREMENT, `isbn` decimal(13,0) NOT NULL, `datum` date NOT NULL, `volgendeDatum` date DEFAULT NULL, `prijs` decimal(8,2) DEFAULT NULL, `prijsExclLaag` decimal(8,2) DEFAULT NULL, `prijsExclHoog` decimal(8,2) DEFAULT NULL, `stadiumDienstverlening` char(2) COLLATE utf8mb4_unicode_520_ci DEFAULT NULL, `stadiumLevenscyclus` char(1) COLLATE utf8mb4_unicode_520_ci DEFAULT NULL, `gewicht` double(7,3) DEFAULT NULL, `volume` double(7,3) DEFAULT NULL, `24uurs` tinyint(1) DEFAULT NULL, `UitgeverCode` varchar(4) COLLATE utf8mb4_unicode_520_ci DEFAULT NULL, `imprintId` int(11) DEFAULT NULL, `distributievormId` tinyint(4) DEFAULT NULL, `boeksoort` char(1) COLLATE utf8mb4_unicode_520_ci DEFAULT NULL, `publishingStatus` tinyint(4) DEFAULT NULL, `productAvailability` tinyint(4) DEFAULT NULL, `voorraadAlles` mediumint(8) unsigned DEFAULT NULL, `voorraadBeschikbaar` mediumint(8) unsigned DEFAULT NULL, `voorraadGeblokkeerdEigenaar` smallint(5) unsigned DEFAULT NULL, `voorraadGeblokkeerdCB` smallint(5) unsigned DEFAULT NULL, `voorraadGereserveerd` smallint(5) unsigned DEFAULT NULL, `fondskosten` enum('depot leverbaar','depot onleverbaar','POD','BOV','eBoek','geen') COLLATE utf8mb4_unicode_520_ci DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `ISBN+datum` (`isbn`,`datum`) USING BTREE, KEY `UitgeverCode` (`UitgeverCode`), KEY `Imprint` (`imprintId`), KEY `VolgendeDatum` (`volgendeDatum`), KEY `Index op voorraad om maxima snel te vinden` (`isbn`,`voorraadAlles`) USING BTREE, KEY `fondskosten` (`fondskosten`), KEY `Datum+isbn+fondskosten` (`datum`,`isbn`,`fondskosten`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=16519430 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_520_ci

我们的虚拟网络+数据库+邮件服务器的配置:

MariaDB 10.4 InnoDB CentOs7 phpMyAdmin 4.9.5 php 5.6 Apache

我们从虚拟网络服务器的默认设置中更改了一些重要的 mariadb 配置参数:

[mysqld] innodb_buffer_pool_size=2G innodb_buffer_pool_instances=4 innodb_flush_log_at_trx_commit=2 tmp_table_size=64M max_heap_table_size=64M join_buffer_size=4M sort_buffer_size=8M optimizer_search_depth=5


mysql configuration phpmyadmin mariadb
4个回答
1
投票

经过多次测试后发现,phpMyAdmin 添加的

LIMIT 0,25

是唯一导致极端延迟的原因。专家可以发现 mysqli/phpmyadmin 和直接在 mariadb 服务器上执行它没有任何区别。

有时,查询中非常小的差异(例如为只返回一条记录的查询添加 LIMIT)可能会导致查询花费 100.000 的时间,因为它将扫描整个索引,因为引擎会看到适合该查询的另一种策略。这是标准行为。

我们已经找到了消除这个特定问题的索引,但现在我们也确信我们的数据库没有任何问题。我们不确定,因为这似乎是极端行为。所以,无事生非。


0
投票
当然

phpmyadmin 为查询添加了 LIMIT。这给出了主要的解释。我不敢相信这不是我们第一次尝试,我很尴尬。 但是,phpMyAdmin 和 mysqli 的速度差异还是很大,结果也还是不同(2020-05-01 在服务器上还是 mysqli 上):

+----------------------------+----------+ | Variable_name | Value | +----------------------------+----------+ | Handler_commit | 1 | | Handler_read_first | 1 | | Handler_read_next | 11733306 | | rest | 0 | +----------------------------+----------+

limit

和2020-05-02的速度:都在0.17-0.2左右

limit
和 2020-05-01 加快速度: php/mysqli:声称:3.5 秒,但页面加载大约 30 秒 putty/mariadb:声称也是 3.5 秒,但在大约 30 秒后显示结果 phpmyadmin:声称实时约 60 秒

EXPLAIN 确实在 LIMIT 下发生了很大变化:

(第 1268 行有数据

+------+-------------+------------------+-------+------------------------------------+------------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+------------------+-------+------------------------------------+------------+---------+------+------+-------------+ | 1 | SIMPLE | TitelDaggegevens | index | fondskosten,Datum+isbn+fondskosten | ISBN+datum | 9 | NULL | 1351 | Using where | +------+-------------+------------------+-------+------------------------------------+------------+---------+------+------+-------------+ <20200501 and 1351 with datum<20200502)



0
投票

SELECT * FROM `TitelDaggegevens` WHERE `datum` BETWEEN '2020-03-31' AND '2020-05-02' AND `fondskosten` IS NULL ORDER BY ISBN;



0
投票

有没有办法从 phpmyadmin 获取

EXPLAIN

?如果是这样,这可能会提供另一个线索。

处理程序编号强烈暗示使用了不同的 

EXPLAIN

显然 phpmyadmin 修改了查询(至少通过添加 

LIMIT

)。我想知道它是否意外地扰乱了查询。您当时是否开启了Slowlog或General日志?要么应该有 SQL

as run

(fondskosten)

上的索引替换为

INDEX(fondskosten, datum)
应该会提高性能。
(“发送数据”一如既往,是引擎提供的无用信息。)

建议通过 mariadb.com 提交错误。

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