为什麽我们一般会在自增列或交易时间列上建立聚集索引



为什麽我们一般会在自增列或交易时间列上建立聚集索引?

到新公司上班也有一段时间了,感觉现在的自己才开始慢慢学习SQL~

看这篇文章之前,大家可以先看一下我之前写的一篇文章

聚集索引表插入数据和删除数据的方式是怎样的

一般的交易系统里面我们都会以自增列或交易时间列作为聚集索引列,因为一般这些系统都是写多读少

每天的交易数据会不停的插入到数据库,但是读取数据就没有数据插入那么频繁

因为这些系统一般是写多读少,所以我们会选择在自增列或交易时间列上建立聚集索引


测试

测试环境:SQLSERVER2012 SP1  WINDOWS7 64位

我们来做一个测试,测试脚本如下:

复制代码
 1 --测试脚本  插入性能
 2 USE [test]
 3 GO
 4 --建表 以transtime为聚集索引列
 5 CREATE TABLE transtable(tranid INT ,transtime DATETIME)
 6 GO
 7 CREATE CLUSTERED INDEX CIX_transtable ON [dbo].[transtable]([transtime])
 8 GO
 9 
10 --建表 以tranid为聚集索引列
11 CREATE TABLE transtable2(tranid INT ,transtime DATETIME)
12 GO
13 CREATE CLUSTERED INDEX CIX_transtable2 ON [dbo].[transtable2]([tranid])
14 GO
15 
16 
17 ----------------------------------------------------------
18 --先插入测试数据,插入的tranid都为基数
19 DECLARE @i INT
20 SET @i = 1
21 WHILE @i <= 1000000
22     BEGIN 
23         INSERT  INTO [dbo].[transtable]
24                 SELECT  @i , GETDATE()
25         SET @i = @i + 2
26     END
27 --------------------------------------
28 DECLARE @i INT
29 SET @i = 1
30 WHILE @i <= 1000000
31     BEGIN 
32         INSERT  INTO [dbo].[transtable2]
33                 SELECT  @i , GETDATE()
34         SET @i = @i + 2
35     END
36 
37 -------------------------------------------
复制代码

在transtable表上的transtime(交易时间)上建立聚集索引,在transtable2表上的tranid(交易编号)上建立聚集索引

我们分别在两个表上插入500000条记录,插入的时候有个特点,就是插入的tranid都是基数

1 SELECT COUNT(*) FROM [dbo].[transtable]
2 SELECT COUNT(*) FROM [dbo].[transtable2]
3 
4 SELECT TOP 10 * FROM [dbo].[transtable] ORDER BY [tranid]
5 SELECT TOP 10 * FROM [dbo].[transtable2] ORDER BY [tranid] 

我们创建两个存储过程,这两个存储过程为插入到表数据

复制代码
 1 --------------------------------------------
 2 --创建两个存储过程
 3 CREATE PROC INSERTTranstable
 4 AS
 5     DECLARE @i INT
 6     SET @i = 1
 7     WHILE @i <= 1000
 8         BEGIN 
 9             IF ( @i % 2 = 0 )
10                 BEGIN
11                     INSERT  INTO [dbo].[transtable]
12                             SELECT  @i ,
13                                     GETDATE()
14                     SET @i = @i + 1
15                 END
16             ELSE
17                 BEGIN
18                     SET @i = @i + 1
19                     CONTINUE 
20                 END
21         END
22 ------------------------------------------
23 CREATE PROC INSERTTranstable2
24 AS
25     DECLARE @i INT
26 SET @i = 1
27 WHILE @i <= 1000
28     BEGIN 
29         IF ( @i % 2 = 0 )
30             BEGIN
31                 INSERT  INTO [dbo].[transtable2]
32                         SELECT  @i ,
33                                 GETDATE()
34                 SET @i = @i + 1
35             END
36         ELSE
37             BEGIN
38              SET @i = @i + 1
39                 CONTINUE 
40             END
41     END
42 -----------------------------
复制代码
View Code


测试脚本,测试一下插入到两个表的时间

复制代码
 1 测试插入偶数行的性能
 2 DECLARE @a DATETIME
 3 DECLARE @b DATETIME
 4 SELECT @a=GETDATE()
 5 EXEC INSERTTranstable
 6 SELECT @b=GETDATE()
 7 SELECT @b-@a
 8 --------------------------------------
 9 
10 DECLARE @c DATETIME
11 DECLARE @d DATETIME
12 SELECT @c=GETDATE()
13 EXEC INSERTTranstable2
14 SELECT @d=GETDATE()
15 SELECT @d-@c
复制代码
View Code

验证一下偶数的交易编号是否已经插入到两个表中

1 SELECT TOP 10 * FROM [dbo].[transtable] ORDER BY [tranid]
2 SELECT TOP 10 * FROM [dbo].[transtable2] ORDER BY [tranid] 
View Code

我们看一下时间

第一个表

第二个表

很明显,第一个表比第二个表快,因为的机器的硬盘是固态硬盘,时间差距不是很大,如果是机械硬盘时间差距会大一些,那么究竟为什麽会造成这种情况呢?

我们用下图来解析一下

我们先说第二张表

当交易编号为2的那条记录插入进来的时候,后面的记录都需要向后移动,以使交易编号从小到大排序,因为聚集索引建立在交易编号列上

这个移动时间是有开销的,而且每次偶数交易编号插入到表中,每插入一次就移动一次,而当前面的记录插入到表中的时候移动的记录数就越多

例如:tranid:2,transtime:2014-1-26 31:22.180插入到表中的时候后面的记录都需要移动,而tranid:978,transtime:2014-01-26 00:29:10.830

这条记录插入到表中的时候,后面需要移动的记录数就没有那么多,总之那个开销挺大的。。。

 

第一张表的情况

因为第一张表是以交易时间为聚集索引列的,所以无论交易编号是多少,记录都会插入到表的最后,因为后来的记录的交易时间肯定比前面的记录的交易时间大

这样的话,基本上没有开销


现实系统中的情况

实际系统中,新生成的要插入到表中的交易编号是有可能小于当前表中的某条记录的交易编号的,那么这时候记录插入到表中就需要移位(如果聚集索引建立在交易编号上)

如果聚集索引建立在交易时间上,那么新生成的要插入到表中的交易记录时间肯定会大于当前表中的任何一条交易记录的时间

(除非人为修改系统时间造成当前时间比数据库中的某些记录的交易时间要早)


总结

前公司的数据库有些表在自增列,有些表在交易时间列上建立了聚集索引,在交易时间列上建立聚集索引个人觉得很正常

因为在查询的时候按照交易时间来排序《order by 交易时间》,速度上是很快的,但是除了排序之外还有一个作用就是本文所讲到的

插入数据到表中的效率问题

个人觉得一般商场管理系统,油站管理系统都是这类型系统
 
本文的意见纯属我自己的个人意见, 并不一定适合您的系统,如果交易时间的选择性不是太高的话,那么可能在交易时间或自增列上建立聚集索引就不是太合适了
我们以前的系统的交易时间的选择性是挺高的,而且通常查询都需要按照交易时间排序,那么聚集索引列建立在交易时间上就是比较好了

 

本次实验用到的完整脚本

复制代码
  1 --测试脚本  插入性能
  2 USE [test]
  3 GO
  4 --建表 以transtime为聚集索引列
  5 CREATE TABLE transtable(tranid INT ,transtime DATETIME)
  6 GO
  7 CREATE CLUSTERED INDEX CIX_transtable ON [dbo].[transtable]([transtime])
  8 GO
  9 
 10 --建表 以tranid为聚集索引列
 11 CREATE TABLE transtable2(tranid INT ,transtime DATETIME)
 12 GO
 13 CREATE CLUSTERED INDEX CIX_transtable2 ON [dbo].[transtable2]([tranid])
 14 GO
 15 
 16 ----------------------------------------------------------
 17 --先插入测试数据,插入的tranid都为基数
 18 DECLARE @i INT
 19 SET @i = 1
 20 WHILE @i <= 1000000
 21     BEGIN 
 22         INSERT  INTO [dbo].[transtable]
 23                 SELECT  @i , GETDATE()
 24         SET @i = @i + 2
 25     END
 26 --------------------------------------
 27 DECLARE @i INT
 28 SET @i = 1
 29 WHILE @i <= 1000000
 30     BEGIN 
 31         INSERT  INTO [dbo].[transtable2]
 32                 SELECT  @i , GETDATE()
 33         SET @i = @i + 2
 34     END
 35 
 36 -------------------------------------------
 37 SELECT COUNT(*) FROM [dbo].[transtable]
 38 SELECT COUNT(*) FROM [dbo].[transtable2]
 39 
 40 SELECT TOP 10 * FROM [dbo].[transtable] ORDER BY [tranid]
 41 SELECT TOP 10 * FROM [dbo].[transtable2] ORDER BY [tranid] 
 42 
 43 --------------------------------------------
 44 --创建两个存储过程
 45 CREATE PROC INSERTTranstable
 46 AS
 47     DECLARE @i INT
 48     SET @i = 1
 49     WHILE @i <= 1000
 50         BEGIN 
 51             IF ( @i % 2 = 0 )
 52                 BEGIN
 53                     INSERT  INTO [dbo].[transtable]
 54                             SELECT  @i ,
 55                                     GETDATE()
 56                     SET @i = @i + 1
 57                 END
 58             ELSE
 59                 BEGIN
 60                     SET @i = @i + 1
 61                     CONTINUE 
 62                 END
 63         END
 64 ------------------------------------------
 65 CREATE PROC INSERTTranstable2
 66 AS
 67     DECLARE @i INT
 68 SET @i = 1
 69 WHILE @i <= 1000
 70     BEGIN 
 71         IF ( @i % 2 = 0 )
 72             BEGIN
 73                 INSERT  INTO [dbo].[transtable2]
 74                         SELECT  @i ,
 75                                 GETDATE()
 76                 SET @i = @i + 1
 77             END
 78         ELSE
 79             BEGIN
 80              SET @i = @i + 1
 81                 CONTINUE 
 82             END
 83     END
 84 -----------------------------
 85 
 86 测试插入偶数行的性能
 87 DECLARE @a DATETIME
 88 DECLARE @b DATETIME
 89 SELECT @a=GETDATE()
 90 EXEC INSERTTranstable
 91 SELECT @b=GETDATE()
 92 SELECT @b-@a
 93 --------------------------------------
 94 
 95 DECLARE @c DATETIME
 96 DECLARE @d DATETIME
 97 SELECT @c=GETDATE()
 98 EXEC INSERTTranstable2
 99 SELECT @d=GETDATE()
100 SELECT @d-@c
复制代码
View Code

 

如有不对的地方,欢迎大家拍砖o(∩_∩)o

3
0
(请您对文章做出评价)
« 上一篇: SQLSERVER PRINT语句的换行
» 下一篇: 在SSMS里查看TDS数据包内容
posted @ 2014-01-26 10:39 桦仔 阅读( 1476) 评论( 33) 编辑 收藏
  
#1楼 2014-01-26 10:46 色拉油啊油  
交易时间列上建立聚集索引碎片问题怎么办?
http://pic.cnitblog.com/face/349217/20141207171254.png
  
#2楼 [ 楼主] 2014-01-26 12:36 桦仔  
@dolphinX
引用 交易时间列上建立聚集索引碎片问题怎么办?

碎片问题无论你在交易时间列还是交易编号列上建立聚集索引,碎片都是会有的,你要删除表数据的话,有碎片只能使用重建/重组索引解决
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
根本就不应该 给 交易编号 设置聚集索引。

一个表应该有一个自己的主键字段,把这个主键字段设置为聚集索引。

这样在MSSQL里面,才是效率最高的。

主键字段是业务逻辑无关的,就是说他不会因为业务逻辑改变了,而修改其值。

一般采用int自增。这样插入新纪录就不会引起记录数据的移动。
http://pic.cnitblog.com/face/u17148.jpg?id=03051207
  
#4楼 [ 楼主] 2014-01-26 16:25 桦仔  
@金色海洋(jyk)阳光男孩
引用 根本就不应该 给 交易编号 设置聚集索引。
金色海洋(jyk)阳光男孩大侠您好
一个表应该有一个自己的主键字段,把这个主键字段设置为聚集索引。

这样在MSSQL里面,才是效率最高的。

主键字段是业务逻辑无关的,就是说他不会因为业务逻辑改变了,而修改其值。

一般采用int自增。这样插入新纪录就不会引起记录数据的移动。

我们现在也是使用int自增,不过您说的聚集索引要建立在业务逻辑无关的字段上这个不一定,例如交易时间列
这样在选择交易时间的时候就可以用到聚集索引查找,和排序,而且交易时间也不会修改一般
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
  
#5楼 2014-01-26 17:51 gw2010  
金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。
  
#6楼 [ 楼主] 2014-01-26 23:07 桦仔  
@gw2010
引用 金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
  
#7楼 2014-01-26 23:22 gw2010  
@桦仔
引用 @gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充

我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条数据之类的,所以我是这相意思。
  
#8楼 [ 楼主] 2014-01-26 23:55 桦仔  
@gw2010
引用 @桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条数据之类的,所以我是这相意思。

明白o(∩_∩)o
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
  
#9楼 2014-01-27 10:09 ocean  
@金色海洋(jyk)阳光男孩
其实我是不建议在自增列上建立聚集索引的,实际上如果没有特殊的需要,就不应该有自增列。
什么情况下用自增列?就是你找不到明显主键的时候,比如新闻、Blog这样的系统,你没法说按照标题来做主键,因为标题可能会重复,时间也很难,因为同一时间可能多个人发帖,无论怎么弄都有可能会重复,这时才建立一个自增列来做主键,并且在之上建立聚集索引。

如果是有明显能区分出唯一性的,比如交易编号这种,那直接在交易编号上建立聚集索引就好了,没必要再弄一个自增列。聚集索引应该用于业务上查询最多的字段上,而且这个字段还是唯一性的。对于交易的查询可能交易编号、交易时间都是查询条件中最多的,类似比如订单编号,你打客服,可能直接报订单编号,客服直接就能查到,如果你再额外弄个自增列做聚集索引,明显就没有很好的利用聚集索引的优秀特性。

当然建议是聚集索引上的列最好是不修改的,比如交易编号、订单编号这样的,一旦确定就不会修改,经常修改的字段是不适合做聚集索引的。
  
#10楼 [ 楼主] 2014-01-27 10:13 桦仔  
@ocean
引用 @金色海洋(jyk)阳光男孩
其实我是不建议在自增列上建立聚集索引的,实际上如果没有特殊的需要,就不应该有自增列。
什么情况下用自增列?就是你找不到明显主键的时候,比如新闻、Blog这样的系统,你没法说按照标题来做主键,因为标题可能会重复,时间也很难,因为同一时间可能多个人发帖,无论怎么弄都有可能会重复,这时才建立一个自增列来做主键,并且在之上建立聚集索引。

如果是有明显能区分出唯一性的,比如交易编号这种,那直接在交易编号上建立聚集索引就好了,没必要再弄一个自增列。聚集索引应该用于业务上查询最多的字段上,而且这个字段还是唯一性的。对于交易的查询可能交易编号、交易时间都是查询条件中最多的,类似...

比如新闻、Blog这样的系统,你没法说按照标题来做主键, 很赞同
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
  
#11楼 2014-01-27 13:29 我是大菠萝  
@桦仔
在创建时间上添加聚集索引,对某些分布式场景不太适用;
比如一个比较繁忙的交易系统,可能在订单服务器前有一些接单服务器负责支撑较为繁忙的下单任务,再通过某种同步机制将多点数据汇总到一台服务器上,如果选择在创建时间上添加聚集索引,一是业务的繁忙可能导致多个订单在同一时间创建,这样在检索的时候,还是要通过系统的rowid进行区分;二是由于涉及到前置接单服务器,可能从时间上并不能保证完全一致,这样在写入订单服务器是,仍旧会有页分裂的问题;
因此,我认为,选择能保证写入顺序的主键作为聚集索引才是最优的
http://pic.cnitblog.com/face/568379/20140115123723.png
  
#12楼 [ 楼主] 2014-01-27 15:17 桦仔  
@我是大菠萝
引用 @桦仔
在创建时间上添加聚集索引,对某些分布式场景不太适用;
比如一个比较繁忙的交易系统,可能在订单服务器前有一些接单服务器负责支撑较为繁忙的下单任务,再通过某种同步机制将多点数据汇总到一台服务器上,如果选择在创建时间上添加聚集索引,一是业务的繁忙可能导致多个订单在同一时间创建,这样在检索的时候,还是要通过系统的rowid进行区分;二是由于涉及到前置接单服务器,可能从时间上并不能保证完全一致,这样在写入订单服务器是,仍旧会有页分裂的问题;
因此,我认为,选择能保证写入顺序的主键作为聚集索引才是最优的

确实,时间太快会有很多重复时间,目前我们也是使用自增列为主键的
有空真的要多向菠萝熊学习o(∩_∩)o
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
主键 + 聚集索引 是给数据库用的。

用于数据库的查找记录,修改记录,删除记录,最主要的是做关联。

关系型数据库的特点是啥?关联,就是表与表是怎么连系到一起的。

那么关联的时候你用什么类型的字段?int、datetime、guid、还是字符串?或者是小数?

基本上不是int就是guid。

那么要提高效率,当然是给关联字段加上聚集索引了。


基本就是这样了。
http://pic.cnitblog.com/face/u17148.jpg?id=03051207
@桦仔
引用 @金色海洋(jyk)阳光男孩
引用引用根本就不应该 给 交易编号 设置聚集索引。
金色海洋(jyk)阳光男孩大侠您好
一个表应该有一个自己的主键字段,把这个主键字段设置为聚集索引。

这样在MSSQL里面,才是效率最高的。

主键字段是业务逻辑无关的,就是说他不会因为业务逻辑改变了,而修改其值。

一般采用int自增。这样插入新纪录就不会引起记录数据的移动。

我们现在也是使用int自增,不过您说的聚集索引要建立在业务逻辑无关的字段上这个不一定,例如交易时间列
这样在选择交易时间的时候就可以用到聚集索引查找,和排序,而且交易时间也不会修改一般



你也说了,是 “一般”。

那万一要改呢,麻烦死you。

另外,最需要聚集索引的地方是,关联字段。五百万的表和一万的表做关联,如果关联字段不是聚集索引的话,后果是啥样子的呢?
http://pic.cnitblog.com/face/u17148.jpg?id=03051207
@gw2010
引用 金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。


打好的聚集索引,这个是为数据库自己服务的,完全不是为了业务逻辑。

非聚集索引才是为业务逻辑服务的,主要是查询和排序。
http://pic.cnitblog.com/face/u17148.jpg?id=03051207
  
#16楼 [ 楼主] 2014-01-29 12:00 桦仔  
@金色海洋(jyk)阳光男孩
引用 @桦仔
引用引用@金色海洋(jyk)阳光男孩
引用引用根本就不应该 给 交易编号 设置聚集索引。
金色海洋(jyk)阳光男孩大侠您好
一个表应该有一个自己的主键字段,把这个主键字段设置为聚集索引。

这样在MSSQL里面,才是效率最高的。

主键字段是业务逻辑无关的,就是说他不会因为业务逻辑改变了,而修改其值。

一般采用int自增。这样插入新纪录就不会引起记录数据的移动。

我们现在也是使用int自增,不过您说的聚集索引要建立在业务逻辑无关的字段上这个不一定,例如交易时间列
这样在选择交易时间的时候就可以用到聚集索引查找,和排序,而且交易时间也不会修改一般


你也说...

是啊,主键肯定要想好的,例如是使用int还是bigint,要考虑以后的数据量,我们现在的数据量需要使用bigint来存储,如果表需要做复制,那么更加需要谨慎考虑主键字段了,做了复制不能随便更改主键
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
@gw2010
引用 @桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条数据之类的,所以我是这相意思。



关于查询,要利用非聚集索引。

往往查询都是多个字段查询,比如有时候要按时间段查,有时候要按分类查,有时候按单号查。有的时候多个字段一起查。

显然聚集索引是搞不定的,因为只能给一个字段加聚集索引。

所以说要用非聚集索引。

非聚集索引依赖的是啥呢?聚集索引。这个有时间在细说。
http://pic.cnitblog.com/face/u17148.jpg?id=03051207
  
#18楼 [ 楼主] 2014-01-29 12:05 桦仔  
@金色海洋(jyk)阳光男孩
引用 @gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。


打好的聚集索引,这个是为数据库自己服务的,完全不是为了业务逻辑。

非聚集索引才是为业务逻辑服务的,主要是查询和排序。

看情况吧,如果本身硬盘空间不多,建太多非聚集索引也会占用硬盘空间的
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
  
#19楼 [ 楼主] 2014-01-29 12:07 桦仔  
@金色海洋(jyk)阳光男孩
引用 @gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条数据之类的,所以我是这相意思。

看来金色海洋(jyk)阳光男孩大侠经验丰富
关于查询,要利用非聚集索引...
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
@ocean
引用 @金色海洋(jyk)阳光男孩
其实我是不建议在自增列上建立聚集索引的,实际上如果没有特殊的需要,就不应该有自增列。
什么情况下用自增列?就是你找不到明显主键的时候,比如新闻、Blog这样的系统,你没法说按照标题来做主键,因为标题可能会重复,时间也很难,因为同一时间可能多个人发帖,无论怎么弄都有可能会重复,这时才建立一个自增列来做主键,并且在之上建立聚集索引。

如果是有明显能区分出唯一性的,比如交易编号这种,那直接在交易编号上建立聚集索引就好了,没必要再弄一个自增列。聚集索引应该用于业务上查询最多的字段上,而且这个字段还是唯一性的。对于交易的查询可能交易编号、交易时间都是查询条件中最多的,类似...



对于你说的归纳一下。我喜欢弄个1、2、3。上次归纳了一下,被误会成是逐句批判。冤枉呀,我只是习惯分成几个点来表述我的想法,希望不要误会。


1、对于交易的查询可能交易编号、交易时间都是查询条件中最多的

如果是这样的话,那么聚集索引建立在哪个字段上面?交易编号还是交易时间?

前几天网上抢小米,终于抢到了,但是好几天了都不出库。我去大客户电话,客服说:你可以说点单号或者手机号,我给你查一下订单情况。

这里就是订单号和手机号作为查询条件。

如果说把聚集索引给了点单号,那么订单是有很多的,用订单后可以半秒钟就查询出来,那么用手机号呢?因为没有聚集索引,需要好几秒才能查询出来,这个就……

另外,订单号一定要输入全部吗?输入部分订单号可不可以查询?就是模糊查询 like '%xxxxx%'

如果在某些情况下,可以模糊查询,那么恭喜你,聚集索引被浪费掉了。


2、明显就没有很好的利用聚集索引的优秀特性

聚集索引的优秀特性,我的理解是:这个是给数据库删除数据(快速定位)、关联数据(也就是查找,还是快速定位)用的,另外就是排序。

这个是聚集索引的本职。

另一个就是为非聚集索引服务。有没有想过非聚集索引是咋回事?

说起来话长了,以后再说。

3、当然建议是聚集索引上的列最好是不修改的。

如果把订单号这一类有业务逻辑的作为聚集索引,那么主动权就交给客户了。

我们完全无法决定。万一哪天客户高兴了,我们的订单号规则要改改。当然这个不可怕,可怕的是要把以前的都改过来。

当然这个还不是最可怕的,最可怕的是,你用订单号做了关联字段。

一个订单里有n个商品,商品里用订单号作为关联。然后订单规则要改,而且要把以前的都改过来。嗯嗯

我只是举个例子,这个例子不太好,因为不太可能发生,请领会含义,谢谢。


4、经常修改的字段是不适合做聚集索引的

非常赞同,所以我采用和业务逻辑无关的int自增,这样就完全不会被修改。因为他没有任何业务含义。

当然你可能觉得这种做法太极端了。也许极端了点吧,但是我不用去分析会不会被修改。
http://pic.cnitblog.com/face/u17148.jpg?id=03051207
  
#21楼 2014-02-05 20:25 笑东风  
数据库设计需要依据需求来做,没有一个绝对的好与坏,林兄说的是常用情况,对我而言,我一般会考虑以下因素:
1、聚集索引的长度和稳定性
2、非聚集索引的数量
3、查询对聚集索引的使用方式和使用频率
4、数据操作造成页拆分和页碎片的几率

场景很重要!
http://pic.cnitblog.com/face/174228/20140113231352.png
  
#22楼 [ 楼主] 2014-02-05 20:41 桦仔  
@笑东风
引用 数据库设计需要依据需求来做,没有一个绝对的好与坏,林兄说的是常用情况,对我而言,我一般会考虑以下因素:
1、聚集索引的长度和稳定性
2、非聚集索引的数量
3、查询对聚集索引的使用方式和使用频率
4、数据操作造成页拆分和页碎片的几率

场景很重要!

有时候一开始设计考虑不周,后来慢慢演变,以前不是在自增列上加聚集索引的
这些都是通过理解业务,理解对数据库的影响而改变的,当然我的情况不一定适合您o(∩_∩)o
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
  
#23楼 2014-02-06 22:42 gw2010  
@金色海洋(jyk)阳光男孩
引用 @gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条数据之类的,所以我是这相意思。


关于查询,要利用非聚集索引...

即然金色引用我,我们在这里也讨论一下吧。
首先,我想说的是聚集索引为什么不可以是为了业务?请问查询本月的订单记录时间算业务吗?为什么说非聚集索引才是为了查询? 我也不反问了,我就说明一下我的关点,我理解是这两个都是集索都是为了询查服务,所以聚集索引也可以是为了业务查询。
其次,你说的查询条件多个的情况说需要不同的索引,我前面一直没有说一个聚集索引就可以搞定一切,而且你所说的只能给一个字段加聚集索引这一点可以看出你对索引创建还有一些不清楚,这个可以参考我的博客索引的第二篇(现在我还没有写,后面会写,我写了第一篇,我是才开始写博客,有很多不足的地方,多多指教)
  
#24楼 [ 楼主] 2014-02-06 22:49 桦仔  
@gw2010
引用 @金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条数据之类的,所以我是这相...

gw2010大侠别鸡冻
https://i-blog.csdnimg.cn/blog_migrate/0e2dee58b51005f9a5e9bfa1521f4260.png
  
#25楼 2014-02-06 22:53 gw2010  
@桦仔
引用 @gw2010
引用引用@金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条...

互相交流,相互进步。
洗洗睡觉。
@gw2010
引用 @金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条数据之类的,所以我是这相...



掌握了索引的原理,才能够更好地利用索引,达到我们的目的。

对于索引的理解,我是参照 《字典》来理解的。

一个表里的聚集索引只能有一个,当然这个聚集索引可以给一个字段,也可以给多个字段,但是多个字段必须是“一个整体”的状态。

就是联合主键了。

我知道可以多个字段和在一起,设置聚集索引,但是我个人是从来不用的,我觉得这样效率并不好。

聚集索引是确定位置的,就好比字典里的汉字在第几页。

非聚集索引就好比拼音检索和部首检索。
http://pic.cnitblog.com/face/u17148.jpg?id=03051207
  
#27楼 2014-02-11 11:59 xiaohuazi  
@金色海洋(jyk)阳光男孩
引用 @gw2010
引用引用@金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条...

主键不一定是聚集索引,也可以设置为非聚集索引
非聚集索引按照拼音检索和部首检索不太对我觉得
非聚集索引我觉得是把表数据放在另一张表(姑且叫非聚集索引表吧),这张表只包括创建非聚集索引时候的那几个字段,查找的时候跟聚集索引是一样的,如果select的字段不在非聚集索引表里,就通过聚集索引键(建立聚集索引的第一个字段)到聚集索引里找其他字段的值
http://pic.cnitblog.com/face/572343/20140113095615.png
  
#28楼 2014-02-11 13:24 gw2010  
@金色海洋(jyk)阳光男孩
引用 @gw2010
引用引用@金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条...

直是越描越黑,主键是主键,索引是索引先把这个搞清楚。
  
#29楼 2014-02-11 13:30 gw2010  
@金色海洋(jyk)阳光男孩
引用 @gw2010
引用引用@金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条...

还有这个
我知道可以多个字段和在一起,设置聚集索引,但是我个人是从来不用的,我觉得这样效率并不好。
这个也不要一口咬死,这个得看需要,如果有这咱需求为什么不可以呢。
而且这里还先谈不上效率的问题得看情况。
  
#30楼 2014-02-11 13:33 gw2010  
@金色海洋(jyk)阳光男孩
引用 @gw2010
引用引用@金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比如时间段内的什么什么数据,最近的多少条...

这里的索引你竟然用字典来理解,字典目录就是一个索引,但是他不是数据库索引,数据库索引明明确确的说了是B树,是另外一种数据结构,你用字典来理解很不恰当。
@gw2010
引用 @金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@金色海洋(jyk)阳光男孩
引用引用@gw2010
引用引用@桦仔
引用引用@gw2010
引用引用金色海洋的说法我也反对一下,
大好的一个聚集索引你竟然后要放在与业务无关的列上。

@gw2010大侠我觉得看情况吧,我的新公司现在的系统也是建立在自增列上的啊,不过在同一张表会有其他的非聚集索引做补充
我不是说这种不可以,其实多数都是自增列上,自增列也是有业务的啊。
好多单条的取数,连接,排序都会用到自增列,所以自增列有很多时候很适合聚集索引。
我只是想表达一下索引是为了查询提速,而查询一般是会用到业务,比...


也许不恰当吧,因为我不知道B树是啥样的。我知道二叉树,多叉树,其他的树就都不知道了。

所以对于索引,只能用比喻的方式来理解,也许是不正确的吧。

但是含义应该是对的。
http://pic.cnitblog.com/face/u17148.jpg?id=03051207
  
#32楼 2014-04-24 16:54 吴小双  
题外话,这位博主很有才,总是看一篇文档要顺带看另一篇,销售精英啊
  
#33楼 2924698 2014/4/24 16:57:12 2014-04-24 16:57 1q2w3e4r5t..  
@吴小双
引用 题外话,这位博主很有才,总是看一篇文档要顺带看另一篇,销售精英啊

对于初学者来讲,他们不是太懂,如果你懂了,也可以不看的o(∩_∩)o
站长统计<iframe src="http://tpc.googlesyndication.com/safeframe/1-0-1/html/container.html" style="display: none; visibility: hidden;"></iframe>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值