为数据库添加索引

  就象许多的 PHP 开发者一样,在刚开始建立动态网站的时候,我都是使用相对简单的数据结构。PHP在连接数据库方面的确实是十分方便(译者注:有些人认为PHP在连接不同数据库时没有一个统一的接口,不太方便,其实这可以通过一些扩展库来做到这一点),你无需看大量的设计文档就可以建立和使用数据库,这也是PHP获得成功的主要原因之一。 

  前些时候,一位颇高级的程序员居然问我什么叫做索引,令我感到十分的惊奇,我想这绝不会是沧海一粟,因为有成千上万的开发者(可能大部分是使用 MySQL 的)都没有受过有关数据库的正规培训,尽管他们都为客户做过一些开发,但却对如何为数据库建立适当的索引所知较少,因此我起了写一篇相关文章的念头。

  最普通的情况,是为出现在where子句的字段建一个索引。为方便讲述,我们先建立一个如下的表。

  CREATE TABLE mytable (
     id serial primary key,
     category_id int not null default 0,
     user_id int not null default 0,
     adddate int not null default 0
  );

  很简单吧,不过对于要说明这个问题,已经足够了。如果你在查询时常用类似以下的语句:

   SELECT * FROM mytable WHERE category_id=1; 

  最直接的应对之道,是为category_id建立一个简单的索引:

   CREATE INDEX mytable_categoryid 
     ON mytable (category_id);

  OK,搞定?先别高兴,如果你有不止一个选择条件呢?例如:

   SELECT * FROM mytable WHERE category_id=1 AND user_id=2;

  你的第一反应可能是,再给user_id建立一个索引。不好,这不是一个最佳的方法。你可以建立多重的索引。

  CREATE INDEX mytable_categoryid_userid ON mytable (category_id,user_id);

  注意到我在命名时的习惯了吗?我使用"表名_字段1名_字段2名"的方式。你很快就会知道我为什么这样做了。

  现在你已经为适当的字段建立了索引,不过,还是有点不放心吧,你可能会问,数据库会真正用到这些索引吗? 测试 一下就OK,对于大多数的数据库来说,这是很容易的,只要使用EXPLAIN命令:

  EXPLAIN

   SELECT * FROM mytable 
    WHERE category_id=1 AND user_id=2;

   This  is  what Postgres 7.1 returns (exactly as I expected) 

   NOTICE: QUERY PLAN:

   Index Scan using mytable_categoryid_userid on 
     mytable (cost=0.00..2.02 rows=1 width=16)

  EXPLAIN

以上是postgres的数据,可以看到该数据库在查询的时候使用了一个索引(一个好开始),而且它使用的是我创建的第二个索引。看到我上面命名的好处了吧,你马上知道它使用适当的索引了。

接着,来个稍微复杂一点的,如果有个ORDER BY字句呢?不管你信不信,大多数的数据库在使用order by的时候,都将会从索引中受益。

   SELECT * FROM mytable 
    WHERE category_id=1 AND user_id=2
     ORDER BY adddate DESC;

有点迷惑了吧?很简单,就象为where字句中的字段建立一个索引一样,也为ORDER BY的字句中的字段建立一个索引:

   CREATE INDEX mytable_categoryid_userid_adddate
     ON mytable (category_id,user_id,adddate);

   注意: "mytable_categoryid_userid_adddate" 将会被截短为

   "mytable_categoryid_userid_addda"

   CREATE

   EXPLAIN SELECT * FROM mytable
    WHERE category_id=1 AND user_id=2
     ORDER BY adddate DESC;

   NOTICE: QUERY PLAN:

   Sort (cost=2.03..2.03 rows=1 width=16)
    -> Index Scan using mytable_categoryid_userid_addda 
       on mytable (cost=0.00..2.02 rows=1 width=16)

   EXPLAIN

  看看EXPLAIN的输出,好象有点恐怖啊,数据库多做了一个我们没有要求的排序,这下知道性能如何受损了吧,看来我们对于数据库的自身运作是有点过于乐观了,那么,给数据库多一点提示吧。

  为了跳过排序这一步,我们并不需要其它另外的索引,只要将查询语句稍微改一下。这里用的是postgres,我们将给该数据库一个额外的提示--在ORDER BY语句中,加入where语句中的字段。这只是一个技术上的处理,并不是必须的,因为实际上在另外两个字段上,并不会有任何的排序操作,不过如果加入,postgres将会知道哪些是它应该做的。

   EXPLAIN SELECT * FROM mytable 
    WHERE category_id=1 AND user_id=2
     ORDER BY category_id DESC,user_id DESC,adddate DESC;

   NOTICE: QUERY PLAN:

   Index Scan Backward using 
    mytable_categoryid_userid_addda on mytable 
     (cost=0.00..2.02 rows=1 width=16)

   EXPLAIN

现在使用我们料想的索引了,而且它还挺聪明,知道可以从索引后面开始读,从而避免了任何的排序。

以上说得细了一点,不过如果你的数据库非常巨大,并且每日的页面请求达上百万算,我想你会获益良多的。不过,如果你要做更为复杂的查询呢,例如将多张表结合起来查询,特别是where限制字句中的字段是来自不止一个表格时,应该怎样处理呢?我通常都尽量避免这种做法,因为这样数据库要将各个表中的东西都结合起来,然后再排除那些不合适的行,搞不好开销会很大。

  如果不能避免,你应该查看每张要结合起来的表,并且使用以上的策略来建立索引,然后再用EXPLAIN命令验证一下是否使用了你料想中的索引。如果是的话,就OK。不是的话,你可能要建立临时的表来将他们结合在一起,并且使用适当的索引。

  要注意的是,建立太多的索引将会影响更新和插入的速度,因为它需要同样更新每个索引文件。对于一个经常需要更新和插入的表格,就没有必要为一个很少使用的where字句单独建立索引了,对于比较小的表,排序的开销不会很大,也没有必要建立另外的索引。

  以上介绍的只是一些十分基本的东西,其实里面的学问也不少,单凭EXPLAIN我们是不能判定该方法是否就是最优化的,每个数据库都有自己的一些优化器,虽然可能还不太完善,但是它们都会在查询时对比过哪种方式较快,在某些情况下,建立索引的话也未必会快,例如索引放在一个不连续的存储空间时,这会增加读磁盘的负担,因此,哪个是最优,应该通过实际的使用环境来检验。

  在刚开始的时候,如果表不大,没有必要作索引,我的意见是在需要的时候才作索引,也可用一些命令来优化表,例如MySQL可用"OPTIMIZE TABLE"。

  综上所述,在如何为数据库建立恰当的索引方面,你应该有一些基本的概念了。

原文链接:http://www.yesky.com/111/164611_2.shtml

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在Oracle数据库中,可以通过以下步骤添加索引: 1. 首先选择需要添加索引的表以及需要添加索引的列。 2. 然后使用CREATE INDEX语句创建索引。例如: ``` CREATE INDEX index_name ON table_name (column1, column2, ...); ``` 这将在指定的表上创建一个名为“index_name”的索引,该索引将根据指定的列(column1,column2等)进行排序。 3. 如果需要更高级的索引选项,可以在CREATE INDEX语句中使用其他选项。例如: ``` CREATE INDEX index_name ON table_name (column1, column2, ...) TABLESPACE tablespace_name PCTFREE 10 INITRANS 2; ``` 这将创建一个名为“index_name”的索引,将使用指定的表空间(tablespace_name),并使用10%的空闲空间以及2个并发事务。 4. 添加索引后,可以使用EXPLAIN PLAN语句来检查查询是否使用了新的索引。例如: ``` EXPLAIN PLAN FOR SELECT * FROM table_name WHERE column1 = 'value'; ``` 这将为指定的查询生成一个执行计划,可以从中检查是否使用了新的索引。 注意,在添加索引之前,需要仔细考虑哪些列需要索引,以及如何优化查询性能。添加过多的索引可能会导致性能下降。 ### 回答2: Oracle数据库添加索引是提高查询性能的重要手段之一。下面是关于如何在Oracle数据库添加索引的步骤和注意事项。 1. 确定需要添加索引的表和列:在设计索引之前,首先需要确定需要添加索引的表和列。通常来说,选择那些经常在查询中使用的列作为索引列是最合适的。 2. 判断索引类型:在Oracle数据库中,有多种类型的索引可供选择,如B树索引、位图索引等。根据具体需求和表的结构来选择合适的索引类型。 3. 创建索引:使用CREATE INDEX语句创建索引。例如,创建单列B树索引可以使用如下语句: CREATE INDEX index_name ON table_name(column_name); 4. 考虑索引优化:在创建索引时,你可以通过指定索引参数来优化索引的性能。例如,可以使用PARALLEL参数来指定索引的并行度,使用COMPUTE STATISTICS参数来收集索引的统计信息等。 5. 更新索引统计信息:使用DBMS_STATS包中的过程来更新表和索引的统计信息。这样可以确保Oracle数据库优化查询计划。 6. 测试索引性能:在添加索引之后,需要进行性能测试来验证索引的效果。可以选择一些常见的查询,并比较带索引和不带索引的查询执行时间。 添加索引也需要注意一些事项: 1. 不要滥用索引:虽然索引可以提高查询性能,但是过多的索引也会带来额外的开销。因此,在添加索引之前,需要仔细考虑是否真的需要索引,并在必要的列上添加。 2. 定期维护索引索引需要定期进行维护,包括重新构建索引、更新统计信息等。这样可以保证索引一直保持最佳性能。 3. 考虑空间使用:添加索引会占用额外的存储空间。因此,在创建索引时,需要考虑存储空间的使用情况,并确保有足够的空间来支持索引。 总之,通过合理的索引设计和维护,可以显著提高Oracle数据库的查询性能。但是需要注意的是,在添加索引之前,需要仔细考虑选择的列和索引类型,并定期对索引进行维护。 ### 回答3: Oracle数据库添加索引是为了提高查询效率和加快数据检索的速度。索引是在表或者视图上创建的一种数据结构,可以帮助数据库系统快速定位到具有特定值的数据行。 要添加索引,首先需要确定要创建索引的表或者视图。在确定了目标表或视图之后,可以选择要创建索引的列或者字段。通常选择那些在查询中频繁被用作搜索条件或者参与连接的列或者字段作为索引的候选。 Oracle数据库提供了多种类型的索引,包括B树索引、位图索引、位图联合索引、函数索引等。根据具体的需求和数据结构,选择适合的索引类型。然后使用CREATE INDEX语句创建索引。在创建索引时,可以设置索引的名称、表空间、索引类型、列或者字段列表等信息。 添加索引的优点是可以加快查询的速度,特别是对于大数据量的表或者视图来说,可以显著减少查询时间。但也需要注意,索引并非越多越好,因为索引也会占用存储空间。过多的索引会增加数据库的维护成本,并可能导致更新操作的性能下降。 另外,需要定期对索引进行维护和优化。可以使用索引重建或者在线重组等方法来消除索引的碎片,并保持索引的高效性。 综上所述,Oracle数据库添加索引是一种优化数据库性能的方法,通过创建适当类型的索引来提高查询效率和数据检索速度。但需要根据实际情况进行选择,避免过多索引造成资源浪费,并定期对索引进行维护和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值