❶ 如何利用Mysql命令创建,查看,重建和删除索引
第一步,创建数据库表t_tree_info,命令如下:
create table t_tree_info(
id int(8),
tno int(4),
tname varchar(20),
tdesc varchar(100)
);
如下图所示:
第二步,向表里插入3条数据,插入后查看表记录,如下图所示:
第三步,创建数据库索引tree_name,命令如下:
create index tree_name on t_tree_info (tname(20));
如下图所示:
第四步,查看数据库表索引,利用show命令
show index from t_tree_info;
如下图所示:
第五步,重建索引,利用repari命令
repair table t_tree_info quick;
如下图所示:
第六步,索引创建好了,在不使用该索引时,可以删除
drop index tree_name on t_tree_info;
如下图所示:
❷ 如何重建SQL索引 要具体的命令
USE TableName
DECLARE @TableName varchar(255)
DECLARE TableCursor CURSOR FOR
SELECT table_name FROM information_schema.tables
WHERE table_type = 'base table'
OPEN TableCursor
FETCH NEXT FROM TableCursor INTO @TableName
WHILE @@FETCH_STATUS = 0
BEGIN
DBCC DBREINDEX(@TableName,' ',90)
FETCH NEXT FROM TableCursor INTO @TableName
END
CLOSE TableCursor
DEALLOCATE TableCursor
❸ sql server如何重建索引到其它文件组
在日常工作中,我们发现很多实施案例中,sql server的数据库数据与索引在一起。我见过一个客户的,他的数据库总共大小才60g,但索引与数据完全混在一起,从管理数据库的直觉来看,性能方面肯定有问题,所以我建议他们,不管怎么样,把索引与数据库分开,对性能是有好处的!但是sql server的索引,想要通过重建的方式,把数据与索引分开,并不是一件容易的事怀,在使用rebuild时,并不能增加文件组选项。后来研究发现,可以通过以下方式把数据与非聚簇索引分开,具体如下:
set nocount on
declare @index table
(
object_id int,
objectName sysname,
index_id int,
indexName sysname,
fill_factor tinyint,
allow_row_locks bit,
allow_page_locks bit,
is_padded bit,
indexText varchar(max),
indexTextEnd varchar(max)
)
declare @indexColumn table
(
object_id int,
index_id int,
column_id int,
index_column_id int,
max_index_column_id int,
is_descending_key bit,
is_included_column bit,
columnName varchar(255),
indexText varchar(max) null
)
insert into @index
select
i.object_id,
object_name(i.object_id),
i.index_id,
i.name,
fill_factor,
allow_row_locks,
allow_page_locks,
is_padded,
'CREATE NONCLUSTERED INDEX [' + i.name + '] ON [dbo].[' + object_name(i.object_id) + '] ' + char(13),
'WITH (PAD_INDEX = ' +
CASE WHEN is_padded = 1 THEN ' ON ' ELSE ' OFF ' END +
', STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = ON, ONLINE = OFF, ALLOW_ROW_LOCKS = ' +
CASE WHEN allow_row_locks = 1 THEN ' ON ' ELSE ' OFF ' END +
', ALLOW_PAGE_LOCKS = ' +
CASE WHEN allow_page_locks = 1 THEN ' ON ' ELSE ' OFF ' END +
CASE WHEN fill_factor > 0 THEN ', FILLFACTOR = ' + convert(varchar(3), fill_factor) ELSE '' END +
') ON [IndexFG];print('''+i.name+' @ '+object_name(i.object_id)+''')' --+ CHAR(13) + ' GO;'+ CHAR(13) --注意标红的地方,这是新的文件组的名称
from sys.indexes i
where i.type = 2 and not exists(select 1 from sys.key_constraints kc where kc.name=i.name)
and objectproperty(i.object_id , 'IsUserTable') = 1
order by object_name(i.object_id), i.name
insert into @indexColumn
select
i.object_id,
i.index_id,
ic.column_id,
ic.index_column_id,
max(ic.index_column_id) over (partition by i.object_id, i.index_id, is_included_column),
is_descending_key,
is_included_column,
'[' + c.name + ']',
null
from @index i
join sys.index_columns ic
on i.object_id = ic.object_id
and i.index_id = ic.index_id
join sys.columns c
on ic.object_id = c.object_id
and ic.column_id = c.column_id
order by i.object_id, i.index_id, ic.index_column_id
declare @fields varchar(max)
declare @object_id int, @index_id int
select @fields = null, @object_id = -1, @index_id = -1
update @indexColumn
set @fields = indexText =
case when object_id = isnull(@object_id, object_id) and index_id = isnull(@index_id, index_id)
then isnull(@fields + ', ', ' ') + columnName + case when is_descending_key = 0 then ' ASC' else ' DESC' end
else columnName + case when is_descending_key = 0 then ' ASC' else ' DESC' end
end,
@object_id = case when object_id <> @object_id
then object_id else @object_id end,
@index_id = case when index_id <> @index_id
then index_id else @index_id end
from @indexColumn
where is_included_column = 0
select @fields = null, @object_id = -1, @index_id = -1
update @indexColumn
set @fields = indexText =
case when object_id = isnull(@object_id, object_id) and index_id = isnull(@index_id, index_id)
then isnull(@fields + ', ', ' ') + columnName
else columnName
end,
@object_id = case when object_id <> @object_id
then object_id else @object_id end,
@index_id = case when index_id <> @index_id
then index_id else @index_id end
from @indexColumn
where is_included_column = 1
update @index
set indexText = i.indexText + '( ' + char(13) + char(9) + ic.indexText + char(13) + ') '
from @index i join @indexColumn ic
on i.object_id = ic.object_id
and i.index_id = ic.index_id
and ic.index_column_id = ic.max_index_column_id
and ic.is_included_column = 0
update @index
set indexText = i.indexText + 'INCLUDE ( ' + char(13) + char(9) + ic.indexText + char(13) + ') '
from @index i join @indexColumn ic
on i.object_id = ic.object_id
and i.index_id = ic.index_id
and ic.index_column_id = ic.max_index_column_id
and ic.is_included_column = 1
update @index
set indexText = indexText + indexTextEnd
from @index
select indexText, objectName, indexName
from @index
最后的查询结果第一行就是执行的命令!
❹ 在PL-SQL中如何给oracle数据库重建索引
重建索引有多种方式,如drop and re-create、rebuild、rebuild online等。下面简单比较这几种方式异同以及优缺点:
首先建立测试表及数据:
SQL> CREATE TABLE TEST AS SELECT CITYCODE C1 FROM CITIZENINFO2;
Table created
SQL> ALTER TABLE TEST MODIFY C1 NOT NULL;
Table altered
SQL> SELECT COUNT(1) FROM TEST;
COUNT(1)
----------
16000000
一、drop and re-create和rebuild
首先看看正常建立索引时,对表的加锁情况。
suk@ORACLE9I> @show_sid
SID
----------
14
suk@ORACLE9I> CREATE INDEX IDX_TEST_C1 ON TEST(C1);
索引已创建。
SQL> SELECT OBJECT_NAME,LMODE FROM V$LOCK L,DBA_OBJECTS O WHERE O.OBJECT_ID=L.ID1 AND L.TYPE='TM' AND SID=14;
OBJECT_NAME LMODE
------------------------------ ----------
OBJ$ 3
TEST 4
可见,普通情况下建立索引时,oracle会对基表加share锁,由于share锁和 row-X是不兼容的,也就是说,在建立索引期间,无法对基表进行DML操作。
对于删除重建索引的方法就不介绍了,它与上面的描述是一样的,下面我们看看用rebuild的方式建立索引有什么特别。
suk@ORACLE9I> ALTER INDEX IDX_TEST_C1 REBUILD;
索引已更改。
另开一个会话,查询此时test的加锁情况:
SQL> SELECT OBJECT_NAME,LMODE FROM V$LOCK L,DBA_OBJECTS O WHERE O.OBJECT_ID=L.ID1 AND L.TYPE='TM' AND SID=14;
OBJECT_NAME LMODE
------------------------------ ----------
TEST 4
可见,rebuild的方式对基表的加锁方式与CREATE时是一样的。
另开一个会话,在索引正在rebuild时,执行如下SQL:
suk@ORACLE9I> SET AUTOTRACE TRACE
suk@ORACLE9I> SELECT /*+ INDEX(TEST) */ COUNT(1) FROM TEST WHERE ROWNUM<10;
执行计划
----------------------------------------------------------
0 SELECT STATEMENT ptimizer=CHOOSE (Cost=26 Card=1)
1 0 SORT (AGGREGATE)
2 1 COUNT (STOPKEY)
3 2 INDEX (FULL SCAN) OF 'IDX_TEST_C1' (NON-UNIQUE) (Cost=
26 Card=1986621)
可以看到索引在重建时,查询仍然可以使用旧索引。实际上,oracle在rebuild时,在创建新索引过程中,并不会删除旧索引,直到新索引rebuild成功。
从这点可以知道rebuild比删除重建的一个好处是不会影响原有的SQL查询,但也正由于此,用rebuild方式建立索引需要相应表空间的空闲空间是删除重建方式的2倍。
重建索引有多种方式,如drop and re-create、rebuild、rebuild online等。下面简单比较这几种方式异同以及优缺点:
相关文章:
oracle重建索引(一)
二、rebuild 和rebuild online
首先我们跟踪一下rebuild online的过程。
另开一个会话查看锁的信息:
SQL> SELECT OBJECT_NAME,LMODE FROM V$LOCK L,DBA_OBJECTS O WHERE O.OBJECT_ID=L.ID1 AND L.TYPE='TM' AND SID=14;
OBJECT_NAME LMODE
------------------------------ ----------
SYS_JOURNAL_10499 4
TEST 2
SQL> INSERT INTO TEST VALUES(11);
1 row inserted
SQL> COMMIT;
Commit complete
可以看到,在rebuild online期间,oracle对基表加的是RS所,此时我们可以对基表进行DML操作。但奇怪的话在相同的session中有一个SYS_JOURNAL_10499表被加SHARE锁,这个表是干什么用的呢?
我们看看trace文件,有这样的信息:
create table "SUK"."SYS_JOURNAL_10499" (C0 NUMBER(6,0), opcode char(1),
partno number, rid rowid, primary key( C0 , rid )) organization index
TABLESPACE "TEST"
CREATE UNIQUE INDEX "SUK"."SYS_IOT_TOP_10605" on
"SUK"."SYS_JOURNAL_10499"("C0","RID") INDEX ONLY TOPLEVEL TABLESPACE "TEST"
NOPARALLEL
drop table "SUK"."SYS_JOURNAL_10499"
我们在查查10499是什么东西:
SQL> SELECT OBJECT_NAME,OBJECT_TYPE FROM DBA_OBJECTS WHERE OBJECT_ID=10499;
OBJECT_NAME OBJECT_TYPE
------------------------------ ------------------
IDX_TEST_C1 INDEX
从这些信息可以推测:表SYS_JOURNAL_10499就是实现在重建索引时不阻塞DML操作而设计的,它存储的是在索引重建期间发生在基表的数据变化。可以推测,CREATE INDEX .... ONLINE应该也有一张类似的表。
实际上,oracle之所以在创建索引时锁表阻止DML操作就是为了防止不能索引新变化的数据,在online方式重建时,有了临时表SYS_JOURNAL_XXXX,oracle就可以放心大胆地让用户操作了,因为所有重建索引期间的数据变化信息都会保留在SYS_JOURNAL_XXX表中,当索引重建完后再加上SYS_JOURNAL_XXX记录的数据,就不会漏索引数据了。(XXX是被重建的索引对应的OBJECT_ID)
导读:
重建索引有多种方式,如drop and re-create、rebuild、rebuild online等。下面简单比较这几种方式异同以及优缺点:
相关文章:
oracle重建索引(一)
oracle重建索引(二)
三、rebuild和rebuild online的数据源
网上一直有这样一个说法:重建索引是以原索引作为数据源的。那么,这种说法是否准确呢?我们做实验来验证一下:
suk@ORACLE9I> COL SEGMENT_NAME FORMAT A30
--首先看看表和索引的大小
suk@ORACLE9I> SELECT SEGMENT_NAME,BYTES FROM USER_SEGMENTS WHERE SEGMENT_NAME IN ('TEST','IDX_TEST_C1');
SEGMENT_NAME BYTES
------------------------------ ----------
TEST 201326592
IDX_TEST_C1 293601280
suk@ORACLE9I> EXPLAIN PLAN FOR ALTER INDEX IDX_TEST_C1 REBUILD;
已解释。
suk@ORACLE9I> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------
| 0 | ALTER INDEX STATEMENT | | | | |
| 1 | INDEX BUILD NON UNIQUE| IDX_TEST_C1 | | | |
| 2 | SORT CREATE INDEX | | | | |
| 3 | TABLE ACCESS FULL | TEST | | | |
-----------------------------------------------------------------------
Note: rule based optimization
已选择11行。
--从执行计划可以看出,当索引比表大时,rebuild索引用的数据源是基表。
suk@ORACLE9I> EXPLAIN PLAN FOR ALTER INDEX IDX_TEST_C1 REBUILD ONLINE;
已解释。
suk@ORACLE9I> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------
| 0 | ALTER INDEX STATEMENT | | | | |
| 1 | INDEX BUILD NON UNIQUE| IDX_TEST_C1 | | | |
| 2 | SORT CREATE INDEX | | | | |
| 3 | TABLE ACCESS FULL | TEST | | | |
-----------------------------------------------------------------------
Note: rule based optimization
已选择11行。
--从执行计划可以看出,当索引比表大时,rebuild online索引用的数据源是基表。
--我们为TEST添加一列,使得表比索引大
suk@ORACLE9I> ALTER TABLE TEST ADD(C2 CHAR(30) DEFAULT '1');
表已更改。
suk@ORACLE9I> SELECT SEGMENT_NAME,BYTES FROM USER_SEGMENTS WHERE SEGMENT_NAME IN ('TEST','IDX_TEST_C
1');
SEGMENT_NAME BYTES
------------------------------ ----------
TEST 1476395008
IDX_TEST_C1 293601280
suk@ORACLE9I> EXPLAIN PLAN FOR ALTER INDEX IDX_TEST_C1 REBUILD;
已解释。
suk@ORACLE9I> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------
| 0 | ALTER INDEX STATEMENT | | | | |
| 1 | INDEX BUILD NON UNIQUE| IDX_TEST_C1 | | | |
| 2 | SORT CREATE INDEX | | | | |
| 3 | INDEX FAST FULL SCAN| IDX_TEST_C1 | | | |
-----------------------------------------------------------------------
Note: rule based optimization
已选择11行。
--从执行计划可以看出,当表比索引大时,执行计划已经改变,rebuild索引是以索引作为数据源的。
suk@ORACLE9I> EXPLAIN PLAN FOR ALTER INDEX IDX_TEST_C1 REBUILD ONLINE;
已解释。
suk@ORACLE9I> SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY());
PLAN_TABLE_OUTPUT
----------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost |
-----------------------------------------------------------------------
| 0 | ALTER INDEX STATEMENT | | | | |
| 1 | INDEX BUILD NON UNIQUE| IDX_TEST_C1 | | | |
| 2 | SORT CREATE INDEX | | | | |
| 3 | TABLE ACCESS FULL | TEST | | | |
-----------------------------------------------------------------------
Note: rule based optimization
已选择11行。
--从执行计划可以看出,当表比索引大时,rebuild online仍然以基表作为数据源。
rebuild模式下,因为表数据不会产生变化,oracle主要考虑性能问题,把更快扫描完成的段作为数据源。在上面的例子中,我们并没有对表进行分析,故oracle应该根据数据段的大小来决定那个作为数据源的。一般索引字段比较多,或者对索引字段的DML操作较多,可能会导致索引比表大,这时oracle就会使用基表作为新索引的数据源进行rebuild了。
而在rebuild online模式下,因为允许DML操作,而表数据变化的同时索引也会跟着变化,为了索引与基表数据的一致性,比如采用基表数据作为数据源,而不能用原索引数据作为数据源。
我们用反证法证明不能用原索引作为新索引的数据源。
例如:
T1发出rebuild online命令
T2删除某条数据,删数据的同时,oracle会自动维护了旧索引
T3扫描经过T2数据所在索引节点
T4插入一条记录,新记录对应的索引节点刚好重用了T2删除的数据对应的索引节点空间
如果是这样的话,新建的索引将不包含T4插入的记录的信息。所以,rebuild online情况下新索引的数据源不能是原索引。
rebuild online情况下,如果非用原索引作为新索引的数据源的话,用中间表记录索引变化的方法应该是可以实现的,但由于数据变化会同时引起索引变化的特定决定了这种方法将异常复杂及效率底下,所以oracle不考虑旧索引作为新索引的数据源是有道理的。
结论:
1、rebuild会阻塞对基表的DML操作,但不会影响rebuild期间查询对原有索引的使用。
2、rebuild的数据源可能是基表,也可能是原索引。取决于基表和原索引的大小,那个小,rebuild时就会用那个作为数据源。这也说明了网上盛传的rebuild以原索引作为数据库的说法是不完全正确的。
3、rebuild online运行用户在索引重建期间执行DML操作。
4、rebuild online的数据源是基表
❺ sql server 重新生成索引可以减小数据库空间吗
sql server 重新生成索引可以减小数据库空间。
理由分析:
一、重新生成索引:
1、命令: ALTER INDEX 索引名 on 表名 REBUILD
2、解析:重新生成索引将删除该索引并创建一个新索引。此过程中将删除碎片,通过使用指定的或现有的填充因子设置压缩页来回收磁盘空间,并在连续页中对索引行重新排序(根据需要分配新页)。这样可以减少获取所请求数据所需的页读取数,从而提高磁盘性能。
二、重新组织索引:
1、命令:ALTER INDEX 索引名 on 表名 reorganize
2、解析: 重新组织索引是通过对叶页进行物理重新排序,使其与叶节点的逻辑顺序(从左到右)相匹配,从而对表或视图的聚集索引和非聚集索引的叶级别进行碎片整理。使页有序可以提高索引扫描的性能。索引在分配给它的现有页内重新组织,而不会分配新页。如果索引跨多个文件,将一次重新组织一个文件,不会在文件之间迁移页。
重新组织还会压缩索引页。如果还有可用的磁盘空间,将删除此压缩过程中生成的所有空页。压缩基于 sys.indexes 目录视图中的填充因子值。
重新组织进程使用最少的系统资源。而且,重新组织是自动联机执行的。该进程不持有长期阻塞锁,所以不会阻止运行查询或更新。
索引碎片不太多时,可以重新组织索引。
❻ sql server 怎么建立索引
创建索引:
(1)在SQL Server Management Studio中,选择并右击要创建索引的表,从弹出菜单中选择“设计”,打开表设计器。右键单击表设计器,从弹出菜单中选择“索引/键”命令,打开“索引/键”对话框。对话框中列出了已经存在的索引,如下图所示。
(2)单击“添加”按钮。在“选定的主/唯一键或索引”框显示系统分配给新索引的名称。
(3)在“列”属性下选择要创建索引的列。可以选择多达16列。为获得最佳性能,最好只选择一列或两列。对所选的每一列,可指出索引是按升序还是降序组织列值。
(4)如果要创建唯一索引,则在“是唯一的”属性中选择“是”。
(5)设置完成后,单击“确定”按钮。
(6)当保存表时,索引即创建在数据库中。
使用CREATE INDEX语句创建索引:
复制内容到剪贴板
代码:
CREATE[ UNIQUE ] [ CLUSTERED | NONCLUSTERED ] INDEX索引名
ON {表名|视图名} (列名[ ASC | DESC ] [ ,...n ] )
例:
在数据库HrSystem中为表Employees创建基于IDCard列的唯一索引IX_Employees,可以使用以下命令:
复制内容到剪贴板
代码:
USE HrSystem
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_Employees]ONdbo.Employees(IdCard)
GO
例:
为表Employees创建基于列IDCard的唯一、聚集索引IX_Employees1,可以使用以下命令:
复制内容到剪贴板
代码:
USE HrSystem
GO
CREATE UNIQUE CLUSTERED INDEX [IX_Employees1] ON [dbo].[Employees](IdCard)
GO
需要注意的是,在一个表中只允许存在一个聚集索引。因此,如果表Employees中已经存在一个聚集索引,则执行上面的语句时将会提示下面的错误信息。
消息1902,级别16,状态3,第1行
无法对表'dbo.Employees'创建多个聚集索引。请在创建新聚集索引前删除现有的聚集索引'PK__Employee__263E2DD300551192'。 例:
对表Employees的列Emp_name按照降序创建索引,可以使用以下命令:
复制内容到剪贴板
代码:
USE HrSystem
GO
CREATENONCLUSTERED INDEX [IX_Employees2] ON [dbo].[Employees]
(
[Emp_name] DESC
)
GO
在CREATE INDEX语句中使用INCLUDE子句,可以在创建索引时定义包含的非键列,其语法结构如下:
复制内容到剪贴板
代码:
CREATENONCLUSTERED INDEX 索引名
ON { 表名| 视图名 } ( 列名 [ ASC | DESC ] [ ,...n ] )
INCLUDE (<列名1>, <列名2>, [,… n])
例: 在表Employees上创建非聚集索引IX_Wage,索引中的键列为Wage,非键列为Emp_name、Sex和Title,具体语句如下:
复制内容到剪贴板
代码:
USEHrSystem
GO
CREATENONCLUSTERED INDEX IX_Wage
ON Employees ( Wage )
INCLUDE (Emp_name, Sex, Title)
GO
例: 在创建索引IX_Wage后,当表Employees中的数据量比较大时,执行下面的SELECT语句将会明显地改进查询效率。
复制内容到剪贴板
代码:
USEHrSystem
GO
SELECTEmp_name, Sex, Title, Wage
FROMEmployees
WHEREWage BETWEEN 1000 AND 3000
GO
❼ sql server2008 相隔10天自动删除索引,然后再重新创建。(高手速来。悬赏大大滴)
思路:
1、创建存储过程,内容是删除存储过程,并重建索引
2、创建作业,然后作业内容是调用上面的存储过程(切记,执行此存储过程的用户一定要有权限,最好是该数据库的dbowen),然后设置该作业自动执行的周期
3、恭喜你以后省事了!
❽ SQL中如何重建一张表的索引
SELECT
tab.name AS [表名],
idx.name AS [索引名称],
col.name AS [列名]
FROM
sys.indexes idx
JOIN sys.index_columns idxCol
ON (idx.object_id = idxCol.object_id
AND idx.index_id = idxCol.index_id
)
JOIN sys.tables tab
ON (idx.object_id = tab.object_id)
JOIN sys.columns col
ON (idx.object_id = col.object_id
AND idxCol.column_id = col.column_id);