索引和多列主键

时间:2010-06-15 18:55:03

标签: sql mysql primary-key indexing

搜索并没有找到这个特定的菜鸟问题的答案。如果我错过了,我道歉。

在MySQL数据库中,我有一个包含以下主键的表

PRIMARY KEY id(发票,项目)

在我的应用程序中,我还经常选择“项目”本身,而不是经常选择“发票”。我假设我会从这些列的索引中受益。

当我定义以下内容时,MySQL不会抱怨:

INDEX(发票),   INDEX(项目),   PRIMARY KEY id(发票,项目)

但我没有看到任何证据(使用DESCRIBE - 我知道如何查看的唯一方法)已经为这两列建立了单独的索引。

所以问题是,构成主键的列是否会单独自动编入索引?另外,有没有比DESCRIBE更好的方法来探索我的桌子的结构?

6 个答案:

答案 0 :(得分:42)

我对mySql的索引内部并不是很熟悉,但是我熟悉的两个数据库供应商产品(MsSQL,Oracle)索引是平衡树结构,其节点被组织为一个有序的元组。索引定义的列( 在序列定义中

因此,除非mySql以非常不同的方式(可能不是),任何复合索引(在多个列上)可以可被任何需要过滤或排序的查询 > 子集 索引中的列,只要列的列是兼容的,即,如果列的顺序与完整索引中的列的顺序列表相同,是整个索引列的有序子集,从实际索引序列的开头开始,除了最后没有间隙...

换句话说,这意味着如果你在(a,b,c,d)上有索引,那么在(a),(a,b)或(a,b,c)上过滤的查询也可以使用索引,但需要在(b),或(c)或(b,c)上过滤的查询将无法使用索引......

因此,在您的情况下,如果您经常需要单独对列 进行过滤或排序,则需要在该列上添加另一个索引... < / p>

答案 1 :(得分:15)

我个人使用phpMyAdmin来查看和编辑MySQL数据库的结构。它是一个Web应用程序,但它在本地Web服务器上运行良好(我在我的机器上为此运行apache实例和phpPgAdmin)。

对于(invoice, item)的复合键,它的作用类似于(invoice, item)invoice的索引。如果您只想按item索引,则必须自己添加该索引。您的PK将按invoice排序,然后按item排序,其中invoice在多条记录中相同。虽然复合PK中的顺序与唯一性强制无关,但它对访问很重要。

在你的桌子上我会用:

PRIMARY KEY id (invoice, item), INDEX (item)

答案 2 :(得分:4)

要返回表索引信息,您可以使用:

SHOW INDEX FROM <table>;

请参阅:http://dev.mysql.com/doc/refman/5.0/en/show-index.html

查看表格信息:

SHOW CREATE TABLE <table>;

请参阅:http://dev.mysql.com/doc/refman/5.0/en/show-create-table.html

主键是索引,因此无需创建其他索引。您可以在CREATE TABLE语法下找到有关它们的更多信息(这里插入的内容太多了):

http://dev.mysql.com/doc/refman/5.0/en/create-table.html

答案 3 :(得分:3)

我对MySQL并不熟悉,但通常多列索引在索引的第一列上同样有用,仅作为该列的索引。对于单个列,多列索引变得不那么有用,列在索引中显示得越远。

如果您将多列索引视为层次结构,则会有所帮助。索引中的第一列是层次结构的根,因此搜索它只是扫描第一级的问题。但是,为了扫描第二列,数据库必须查找第一列中找到的每个唯一值的树。这可能足够昂贵,大多数优化器都不会费心深入研究多列索引,而是选择全表扫描。

例如,如果您有一个表格如下:

Col1 |Col2 |Col3
----------------
   A |   1 |   Z
   A |   2 |   Y
   A |   2 |   X
   B |   1 |   Z
   B |   2 |   X

假设所有三列都有一个索引,按顺序,树将如下所示:

A
+-1
  +-Z
+-2
  +-X
  +-Y
B
+-1
  +-Z
+-2
  +-X

寻找Col1 ='A'很简单:您只需要查看2个有序值。但是,要解决col3 ='X',您必须查看4个较大存储桶中的所有值,每个存储桶都是单独订购的。

答案 4 :(得分:2)

复合索引和复合主键之间存在差异。 如果您已定义了如下所示的复合索引

INDEX idx(invoice,item)  

如果您根据item进行查询并且需要添加单独的索引

,则索引无效
INDEX itemidx(item)  

但是,如果你已经定义了一个复合主键,如下所示

PRIMARY KEY(invoice, item)  

如果您基于item进行查询,则索引将起作用,并且不需要单独的索引。

工作示例:

mysql>create table test ( col1 int(20), col2 int(20) ) primary key(col1,col2);
mysql>explain select * from test where col2 = 1;
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+
|  1 | SIMPLE      | test  | index | NULL          | PRIMARY | 8       | NULL |   10 | Using where; Using index |
+----+-------------+-------+-------+---------------+---------+---------+------+------+--------------------------+

答案 5 :(得分:0)

Mysql自动为组合键创建索引。根据您的查询,您可能必须为组合键中的各个列创建单独的索引。

如果使用的是mysql工作台,则可以手动右键单击架构,然后单击“编辑”以查看有关表的所有信息