为什么向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!谢谢