jiachunzhou 发表于 2013-01-12 00:19

请教一个超小型表上索引的问题

如果一个表,只有10行,但是业务系统对这个表的读写都很频繁,这时是加索引效率高的还是不加索引效率高?为什么?
对于oracle数据库与sybase数据库,策略上有什么不同吗?

zhangyh123 发表于 2013-01-12 02:28

改成行锁 不加索引

jiachunzhou 发表于 2013-01-12 10:32

回复 2# zhangyh123
能给个解释么?为什么不需要加索引?
如果这个表只有两条记录,记录1的数据为10,记录2的数据为20
当事务A在更改记录1的数据,比如改为11,事务B还能将记录2的数据改为22么?
事务B是否需要等待事务A完成后才能进行更改?

   

fishcoder 发表于 2013-01-14 16:11

本帖最后由 fishcoder 于 2013-01-14 16:15 编辑

如果你的这10条记录完全可以放在一个page上的话,那么不加索引效果比较好(加索引的话会多出来一个扫描索引根节点的操作)
如果10条记录放在2个page上的话,并且你建表的时候确认row是unique的,那么不建立索引效果高
      建立索引开销 (1次索引root页的扫描 + data页的扫描)
      没有建立索引,这里假设等概率,那么扫描的页数肯定小于2个page
如果放在大于3个page的话,那么肯定是建立索引划算了

如果是sybase 的话,用DOL表,只是对data行进行加锁,不给索引行加锁,因此和这个性能和是否加索引无关
如果是oracle的话,据说有多版本一致性读,不会加sh的行锁,其他不清楚

我的理解,仅供参考。
ps:我这里建立的前提是只考虑IO的开销(肯定是逻辑IO),没有考虑CPU的开销
    有索引的话,对索引页的查找是二分查找,log(n)的开销,而没有建立索引的话,相当于表扫,O(n)的开销

yzw_random 发表于 2013-01-14 16:15

回复 3# jiachunzhou


    datarows transaction B不用等transaction A释放。

jiachunzhou 发表于 2013-01-14 17:02

回复 5# yzw_random


    如果没有索引,那么在事务B在update的时候,where条件不会导致全表扫描么?

yzw_random 发表于 2013-01-14 17:14

要建索引的

jiachunzhou 发表于 2013-01-14 21:39

回复 1# jiachunzhou

最近几天查了一些资料,说说我自己对这种情况的理解,不对之处请大家指正
分几种情况讨论
SYBASE与ORACLE的锁机制是不相同的,SYBASE是悲观锁机制,而ORACLE是乐观锁机制
数据库加锁的目的是为了在多用户环境下协调各个事务的读与写的问题。
写的问题比较简单,无论是哪家数据库,再同一时刻,对同一条记录都只允许一个事务进行操作,这很好理解。
写有三种insert,update和delete,insert不去考虑,update和delete在进行操作的时候,通常会有where条件,而定位满足这些where条件的记录就需要对表进行读的操作。
对于同一条记录的访问,可能会有三种可能:
1、幻读:事务T1读取一条指定where条件的语句,返回结果集。此时事务T2插入一行新记录,恰好满足T1的where条件。然后T1使用相同的条件再次查询,结果集中可以看到T2插入的记录,这条新纪录就是幻想。
2、不可重复读取:事务T1读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,然后T1再次查询,发现与第一次读取的记录不同,这称为不可重复读。
3、脏读:事务T1更新了一行记录,还未提交所做的修改,这个T2读取了更新后的数据,然后T1执行回滚操作,取消刚才的修改,所以T2所读取的行就无效,也就是脏数据。
为了解决读的一致性问题,数据库引入了“隔离级别”,在数据库标准中定义了四种隔离级别。
隔离级别从允许的并发副作用(例如,脏读或幻读)的角度进行描述。
ANSI/ISO SQL92标准中一共定义了四种隔离级别,分别是read uncommitted(未提交读),read committed(已提交读),repeatable read(可重复读),serializable(可序列化)
对于oracle来说,通常不加索引比加索引更有效率,因为当事务A锁住表中某一条记录是,另一个事务B在对数据表进行表扫描以匹配满足条件的记录时,由于oracle采用的是乐观锁机制,所以事务B并不会被挂起以等待事务A完成,事务B将直接从redo log中读取事务A锁定的记录进行判断是否满足条件(当然如果redo log中读取的数据正好满足事务B的条件,事务B也会等待直到事务A完成)。
而对于sybase来说,通常加索引比不加索引更有效率,因为当事务A锁住表中某一条记录以进行更改时,如果没有索引,另一事物B将进行表扫描以搜索满足条件的记录,在悲观锁机制情况下,事务B由于试图向事务A正在更改的记录加SHARE(共享)锁不成功而被挂起等待事务A完成,除非数据库将隔离级别配置为“未提交读,也即脏读”。而如果有索引的,将能通过索引直接定位锁需要的数据记录。

以上是最近几天查资料总结的,不知是否正确,欢迎各位大侠指正。

fishcoder 发表于 2013-01-15 09:25

回复 8# jiachunzhou

而对于sybase来说,通常加索引比不加索引更有效率,因为当事务A锁住表中某一条记录以进行更改时,如果没有索引,另一事物B将进行表扫描以搜索满足条件的记录,在悲观锁机制情况下,事务B由于试图向事务A正在更改的记录加SHARE(共享)锁不成功而被挂起等待事务A完成,除非数据库将隔离级别配置为“未提交读,也即脏读”。而如果有索引的,将能通过索引直接定位锁需要的数据记录。

你这个加锁的机制和查找记录的机制是两码事。
不管是什么db,通过索引就可以快速地找出关键字所对应的记录,此处你只有10行记录,那么IO的开销肯定是2,如果你的10行记录只在一个page中的话,那么IO的开销就只有1

无论是否建立索引,如果事务A对一条记录进行更新时,如果你的隔离等级大于等于1的话,那么B事务都需要A事务提交以后才可以对A事务刚才锁住的记录进行加锁,这里和是否建立索引无关

其实还是建议你这边建立索引的,因为你的DML操作比较多,那么在表扫的时候,如果存在Ex-row的锁,那么在扫描的时候必须要等待它提交才能继续读,所以在锁这一层会影响性能

答案仅供参考



   

Eisen 发表于 2013-01-15 20:59

这真是一个好话题。
个人感觉——真如果是超小表又频繁联立采用的话,哪怕超过3个page,也是不加索引的好,因为自15之后,有了hash join,在没有index的情况下可以更快的load进cache然后计算hash出来,当然如果要是频繁更新这个超小表的话,那也还是加索引的好。
页: [1] 2
查看完整版本: 请教一个超小型表上索引的问题