首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解Rand的MySQL选择顺序:为什么在某些情况下使用无关的键?

理解Rand的MySQL选择顺序:为什么在某些情况下使用无关的键?
EN

Stack Overflow用户
提问于 2022-07-23 03:40:21
回答 1查看 42关注 0票数 0

我就是这么做的

代码语言:javascript
复制
# mysql --version
mysql  Ver 14.14 Distrib 5.7.34, for Linux (x86_64) using  EditLine wrapper

案例1:

代码语言:javascript
复制
CREATE TABLE `Foo2` (
  `id` bigint(20) unsigned NOT NULL,
  `column1` int(10) unsigned NOT NULL,
  `column2` int(10) unsigned NOT NULL,
  `column3` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `composite` (`column1`, `column2`, `column3`)
) ENGINE=InnoDB;
# BASH: for i in `seq 1 10000`; do mysql -uroot -p"password" -e "replace into foo_db.Foo2 (\`id\`,\`column1\`,\`column2\`,\`column3\`) values ($((i * 2)), ${i}, $((i + 1)), NOW());" >/dev/null 2>&1; done

以及下面的解释和结果

代码语言:javascript
复制
explain select * from foo_db.Foo2 order by RAND() limit 5;

代码语言:javascript
复制
select count(*) from foo_db.Foo2;
# result : 10000

案例2:

代码语言:javascript
复制
CREATE TABLE `Foo3` (
  `id` bigint(20) unsigned NOT NULL,
  `column1` int(10) unsigned NOT NULL,
  `column2` int(10) unsigned NOT NULL,
  `column3` datetime NOT NULL,
  `created_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  KEY `composite` (`column1`, `column2`, `column3`)
) ENGINE=InnoDB;
# BASH: for i in `seq 1 10000`; do mysql -uroot -p"password" -e "replace into foo_db.Foo3 (\`id\`,\`column1\`,\`column2\`,\`column3\`) values ($((i * 2)), ${i}, $((i + 1)), NOW());" >/dev/null 2>&1; done
代码语言:javascript
复制
explain select * from foo_db.Foo3 order by RAND() limit 5;

代码语言:javascript
复制
explain select `id` from foo_db.Foo3 order by RAND() limit 5;

代码语言:javascript
复制
select count(*) from foo_db.Foo3;
# result : 10000

我不明白的几点

  1. 为什么解释中显示的行数与实际的选择计数(*)不匹配?

  1. 在第1种情况下,为什么在order by RAND()中使用不相关的composite键而possible_keys为null?

  1. 在案例2中,为什么行为与使用select *的案例1不同,但是如果我选择select id,则行为与案例1相同?

  1. 在第2种情况下,为什么在select id结果中没有使用主键id

部分帮助也将不胜感激。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-23 14:29:32

首先,让我列出一系列的事情。这些会处理你的一些问题。

优化器

  • 可以读取数据的BTree或二级索引的BTree。在后一种情况下,索引称为“覆盖”,并通过“使用index".
  • ENGINE=InnoDB表示”表示,“使用SELECT *.
  • Therefore,包含每个辅助索引中的所有PK列。
  • case 1的辅助索引包含SELECT *.
  • Therefore,Case 1和2b所需的所有列,可以使用覆盖索引。如果给出了使用BTree的选择,优化器
  • 通常会选择较小的索引。”也许案例1的辅助索引恰好更小。
  • 主键是与数据“群集”的。

现在请回答你的具体问题。

使用

  1. 和InnoDB,不保留确切的行数;而是在运行时估计行数。Explain的“行”列有时以2的2作为任意一种方式。(有时离得更远)
  2. 为什么要“空”?(见上文,加上.)生命之谜之一。我发现out.
  3. and
  4. SELECT *需要所有的列,但是现在有一些列不在二级索引.SELECT id中--正如上面提到的“最小的”。

有些关联:有关获取表的随机子集的最快算法,请参见。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73087855

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档