首先我会写一些关于我的测试表的信息。 这是包含 665647 行数据的书籍表。 您可以在下面看到它的外观。
我对价格相同的图书进行了 10 次相同的查询
select * from books where price = 10
所有 10 个查询的执行时间为 9 秒 663 毫秒。
我尝试再次运行相同的 10 个查询。 他们的执行时间为 21 秒 996 毫秒。
show index from books;
为我显示了非常有线的数据。 可能的值只有一个!
我做错了什么?我确信索引可以使我们的查询更快,而不是更慢。
我找到了这个话题:MySQL index slowing down query
但说实话,我不太明白这个特别是基数列
在我的表格书籍中,此刻我有两个可能的价格字段值
10 和 30 仍然 show index from books;
显示 1
@Edit1 显示创建桌书
结果:
CREATE TABLE `books` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`description` text COLLATE utf8mb4_unicode_ci NOT NULL,
`isbn` bigint unsigned NOT NULL,
`price` double(8,2) unsigned NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`author_id` bigint unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `books_isbn_unique` (`isbn`),
KEY `books_author_id_foreign` (`author_id`),
KEY `books_price_index` (`price`),
CONSTRAINT `books_author_id_foreign` FOREIGN KEY (`author_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=665648 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
@Edit2
我添加了新索引 create index nameIndex on books (name)
具有大的基数值。
当我尝试执行此查询时 select * from books where name ='Inventore cumque quis.'
在索引创建之前和之后,我可以看到执行时间的差异。
但我仍然不明白索引是如何工作的。我确信一件事 - 如果我在我的数据库中创建新索引,就是使用适合该索引的数据创建新的数据结构。
例如,如果我有价格为 10、30 的 orws,我会得到两个“表格”,其中包含这些价格的行。
答案 0 :(得分:4)
有这么多行具有相同的 price
是否现实?从查询中返回 444K 行是否现实?我问这些是因为查询优化基于“正常”数据。
索引(例如,INDEX(price)
)在查找出现次数较少的 price
时很有用。事实上,如果优化器发现要搜索的值出现的时间超过大约 20%,它就会避开索引。相反,它会简单地忽略索引并执行您首先测试的操作——简单地扫描整个表,忽略任何不匹配的行。
你应该能够看到这一点
EXPLAIN select * from books where price = 10
带和不带索引。或者,您可以尝试:
EXPLAIN select * from books IGNORE INDEX(books_price_index) where price = 10
EXPLAIN select * from books FORCE INDEX(books_price_index) where price = 10
但是,...看来优化器并没有忽略索引。我看到 price
的“基数”是“1”,这意味着该列中只有一个不同的值。这个“统计数据”要么不正确,要么具有误导性。请运行它,看看有什么变化:
ANALYZE TABLE books;
这将通过一些随机探测重新计算统计数据,并且可能将“1”更改为“2”。
一般建议:注意针对伪造数据运行的基准测试。
答案 1 :(得分:0)