MySQL中的基数是什么?

129

什么是MySQL中的基数(Cardinality)?请用简单易懂的语言解释。

如果任何表的索引细节显示字段 group_id 的基数为11,那么这是什么意思?

8个回答

145

最大基数:所有值都是唯一的

最小基数:所有值都相同

某些列被称为高基数列,因为它们有约束条件(如唯一性),禁止您在每行中放置相同的值。

基数是影响数据聚类、排序和搜索能力的属性。因此,在数据库查询规划器中,它是一个重要的度量,是他们选择最佳计划的启发式方法。


15
喜欢使用高深词汇的情况是怎么回事?“Distinctness”这个词不也可以吗?请你翻译。 - Pacerier
12
@Pacerier说: 是的,虽然我认为从事数据库工作的人已经对关系理论、集合论和数学非常熟悉了。而且他们从集合论中借用了这个术语:https://en.m.wikipedia.org/wiki/Cardinality - Alexander Torstling
35
@Pacerier,"Distinctness"是一个比较大的词(比其他词多一个字)。 - Drew
4
@Drew,;) 不适用于词元比较。 - Pacerier
8
@Pacerier,Lexeme是一个词素?“Distinctness”也可以用在那里,不是吗?;) 如果我们足够努力,就可以把整个语言缩减到只有一个词,并通过变化的重复和停顿来表达自己。 - Jason
显示剩余4条评论

38

维基百科对SQL中的cardinality进行了如下总结:

cardinalitySQL(结构化查询语言)中指特定列(属性)中包含的数据值的唯一性。 基数越低,列中的重复元素就越多。 因此,具有最低可能基数的列将对每一行具有相同的值。 SQL数据库使用基数来帮助确定给定查询的最佳查询计划


35

这是索引中唯一值数量的估计。

对于只有单个主键列的表,基数通常应该等于表中的行数。

更多信息


4
应该是“始终等于”而不是“通常应该等于”! - Vérace
1
在我的测试中,对于大表,主键的基数值与count(*)的值不相同。 - John Wong

16

这基本上与一列的唯一性程度相关,根据Kami提供的维基百科文章所述。

考虑它的重要性在于影响索引策略。如果一个低基数列只有两个可能的值,那么索引将不够选择性,没有使用的必要。


6
如果你试图理解何时对一列进行索引是有意义的,那么第二段非常重要。 - VMC

14

基数越高,行的区别就越好。区别有助于通过更少的分支获取数据。

因此,更高的基数值意味着:

  • 读取查询性能更好;
  • 数据库大小更大;
  • 写入查询性能更差,因为隐藏的索引数据正在被更新。

不明白为什么会出现“写查询性能变差,因为正在更新隐藏的索引数据”的情况? - Vérace
是的,还需要做更多的工作来同步事物。 - Zon

12

在数学中,基数是指一组值中的值的数量。一个集合只能包含唯一的值。

例如,假设有一个集合"A",A={1,2,3} - 那么该集合的基数为|3|。

如果集合"A"包含5个值A={10,21,33,42,57},那么基数就是|5|。

SET     VALUES           Cardinality
A       1,2,3                 3
B       10,21,33,42,57        5

在MySQL的上下文中,列的基数意味着该列唯一值的计数。如果您查看主键列(例如table.id)的基数,则该列的基数将告诉您该表包含多少行,因为每行在表中都有一个唯一标识。

您不必在该表上执行“COUNT(*)”以查找它具有多少行,只需查看基数即可。


5

简单来说,基数是表格内行或元组的数量。而列数则称为“度数”。


不正确 - 你可以有数百万行和基数为1(所有值相同)或数百万(如果每行值都是唯一的,则最多达到表中的行数)! - Vérace

5

根据手册

基数(Cardinality)

索引中唯一值数量的估计。通过运行ANALYZE TABLE或myisamchk -a进行更新。 基数是基于存储为整数的统计信息进行计算的,因此即使对于小表,该值也不一定是准确的。 基数越高,MySQL在执行联接时使用索引的可能性就越大。

Percona的分析如下:

CREATE TABLE `antest` (
  `i` int(10) unsigned NOT NULL,
  `c` char(80) default NULL,
  KEY `i` (`i`),
  KEY `c` (`c`,`i`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

mysql> select count(distinct c) from antest;
+-------------------+
| count(distinct c) |
+-------------------+
|               101 |
+-------------------+
1 row in set (0.36 sec)


mysql> select count(distinct i) from antest;
+-------------------+
| count(distinct i) |
+-------------------+
|               101 |
+-------------------+
1 row in set (0.20 sec)

mysql> select count(distinct i,c) from antest;
+---------------------+
| count(distinct i,c) |
+---------------------+
|               10201 |
+---------------------+
1 row in set (0.43 sec)

mysql> show index from antest;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| antest |          1 | i        |            1 | i           | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
| antest |          1 | c        |            1 | c           | A         |        NULL |     NULL | NULL   | YES  | BTREE      |         |
| antest |          1 | c        |            2 | i           | A         |        NULL |     NULL | NULL   |      | BTREE      |         |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set (0.00 sec)

mysql> analyze table sys_users;
+--------------------------------+---------+----------+----------+
| Table                          | Op      | Msg_type | Msg_text |
+--------------------------------+---------+----------+----------+
| antest                         | analyze | status   | OK       |
+--------------------------------+---------+----------+----------+
1 row in set (0.01 sec)


mysql> show index from antest;
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| Table  | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
| antest |          1 | i        |            1 | i           | A         |         101 |     NULL | NULL   |      | BTREE      |         |
| antest |          1 | c        |            1 | c           | A         |         101 |     NULL | NULL   | YES  | BTREE      |         |
| antest |          1 | c        |            2 | i           | A         |       10240 |     NULL | NULL   |      | BTREE      |         |
+--------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+
3 rows in set (0.01 sec)

1
这个答案没有你自己编写的任何内容,它只是从MySQL手册和你链接到的博客文章中拼凑而成。而且格式也极其混乱。 - Siguza
1
现在它清楚地显示了来源并且格式更好。 - carla

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接