为什么向MySQL表中添加重复索引会导致更长的查询执行时间?
也许索引不相关,但我遇到了一个奇怪的问题 这是我的选择查询:为什么向MySQL表中添加重复索引会导致更长的查询执行时间?,mysql,Mysql,也许索引不相关,但我遇到了一个奇怪的问题 这是我的选择查询: SELECT DISTINCT completeAddress FROM DB_M3_Medium.AvailableAddressesV3 where postNr = 1050 ORDER BY completeAddress ASC; 我的索引: create index postNrAndAddress_idx on DB_M3_Medium.AvailableAddressesV3 (completeAddress); c
SELECT DISTINCT completeAddress FROM DB_M3_Medium.AvailableAddressesV3 where postNr = 1050 ORDER BY completeAddress ASC;
我的索引:
create index postNrAndAddress_idx on DB_M3_Medium.AvailableAddressesV3 (completeAddress);
create index postNr_idx on DB_M3_Medium.AvailableAddressesV3 (completeAddress);
create index completeAddress_idx on DB_M3_Medium.AvailableAddressesV3 (completeAddress);
除此之外,我还有一个自动递增id(idIndex
)上的PK
在出现任何手动创建的索引之前,select查询的执行时间为2.4s
然后我创建了索引(一个接一个):
- 第一个索引-select语句执行时间-2.1s
- 第二个索引-选择 语句执行时间-2.8秒
- 第三个索引-select语句 执行时间-12.7秒
+----+-------------+----------------------+-------+-----------------------------------------------------+---------------------+---------+-----+---------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------------+-------+-----------------------------------------------------+---------------------+---------+-----+---------+-------------+
| 1 | SIMPLE | AvailableAddressesV3 | index | postNrAndAddress_idx,postNr_idx,completeAddress_idx | completeAddress_idx | 363 | | 3526406 | Using where |
+----+-------------+----------------------+-------+-----------------------------------------------------+---------------------+---------+-----+---------+-------------+
表结构:
+------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+--------------+------+-----+---------+----------------+
| vej_Navn | varchar(70) | YES | | | |
| husNr | varchar(20) | YES | | | |
| husbogstav | varchar(50) | YES | | | |
| etage | varchar(30) | YES | | | |
| side_DoerNr | varchar(20) | YES | | | |
| stedNavn | varchar(50) | YES | | | |
| postNr | varchar(15) | YES | MUL | | |
| postDistrikt | varchar(50) | YES | | | |
| lev_Adresse_UUID | varchar(50) | YES | | | |
| fiberstatus | varchar(15) | YES | | | |
| kommune_nr | varchar(35) | YES | | | |
| vej_Kode | varchar(35) | YES | | | |
| completeAddress | varchar(120) | YES | MUL | | |
| randomSalt | varchar(5) | YES | | | |
| id | int(11) | NO | PRI | | auto_increment |
+------------------+--------------+------+-----+---------+----------------+
创建表查询:
CREATE TABLE `AvailableAddressesV3` (
`vej_Navn` varchar(70) COLLATE utf8_unicode_ci DEFAULT NULL,
`husNr` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`husbogstav` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`etage` varchar(30) COLLATE utf8_unicode_ci DEFAULT NULL,
`side_DoerNr` varchar(20) COLLATE utf8_unicode_ci DEFAULT NULL,
`stedNavn` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`postNr` varchar(15) CHARACTER SET utf8 DEFAULT NULL,
`postDistrikt` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`lev_Adresse_UUID` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL,
`fiberstatus` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
`kommune_nr` varchar(35) COLLATE utf8_unicode_ci DEFAULT NULL,
`vej_Kode` varchar(35) COLLATE utf8_unicode_ci DEFAULT NULL,
`completeAddress` varchar(120) COLLATE utf8_unicode_ci DEFAULT NULL,
`randomSalt` varchar(5) COLLATE utf8_unicode_ci DEFAULT NULL,
`id` int(11) NOT NULL AUTO_INCREMENT,
UNIQUE KEY `idIndex` (`id`),
KEY `postNrAndAddress_idx` (`postNr`,`completeAddress`),
KEY `postNr_idx` (`postNr`),
KEY `completeAddress_idx` (`completeAddress`)
) ENGINE=InnoDB AUTO_INCREMENT=3552718 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
根据您的解释输出,查询使用的是
completedaddress\u idx
,可能是因为排序/区别,但我猜postNr=1050
(在哥本哈根,对吧?)的行很少,因此使用postNr\u idx
或postnranddress\u idx应该更有效(对几百行进行排序/区分应该几乎是即时的)。某种情况使查询执行计划器错过了最佳查询
我自己从来没有尝试过,但是您可以尝试更新表统计信息的语句,例如key cardinality,它可以改变优化器的工作方式
要么是这样,要么我错过了一些简单的东西——这似乎很可能:)
编辑
在调试时,强制MySQL使用特定的索引是很有用的。试试。我从来没有想到这会是一个问题,或者至少我会得到WorkBench
或JDBC
的通知,并带有一个错误或至少一个警告
我的select查询应如下所示:
SELECT DISTINCT completeAddress FROM DB_M3_Medium.AvailableAddressesV3 where postNr = '4000' ORDER BY completeAddress ASC;
区别在于postNr
的数据类型。之前我没有把它包装在“
这疯狂地改进了选择,然后当我删除orderby
时,执行时间降到了0.07秒
所以基本上是这样的,SELECT
查询没有使用任何索引,因为没有一个索引是合适的。当我进行解释时
我的键列接收空值。我试图强迫它,但没有什么不同
然后我发现:
在第二个答案中,他提到了这一点 你的第一个问题是为什么我的查询会这样做:我猜这是一个复制粘贴错误,但是你添加了三次相同的索引(总是打开completedaddress
)。除了按照CBroe建议显示EXPLAIN语句结果外,还可以发布您的架构。谢谢,请参阅编辑。请注意,每个索引都可能会加快SELECT查询,但会减慢更新/插入/删除速度,因为此索引必须更新。“猜测”添加所有可能的索引是很容易的,希望一切都能运行得更快。但把10个不必要的索引放在大表上,然后看看速度是如何变慢的。不是秒,但查询可能需要0.3秒,而不是0.001秒。对于密集型工作,这是有价值的。对于百万行表,时间可以不是0.3秒,而是3秒。非常感谢@AndreLaszlo,我只使用postNr
索引进行了尝试,现在执行时间是2.6秒,这仍然比根本没有索引要高。太奇怪了。有趣的是,对于那个查询,解释的输出是什么?嗯,但是在执行了解释之后,当我只有postNr
索引时,它说这是一个可能的键,但不是一个选择的键。所选密钥为空。我怎样才能强迫它使用那个钥匙?答案更新了。另外,您如何度量查询时间。这只是为选择本身?不包括创建和插入对吗?啊对不起。读得太快了。太糟糕了!我只是在试验,回来回答完全一样的问题!:)美好的为这样的努力付出+1!谢谢