You are on page 1of 10

--Criao de uma base de dados com 3 filegroups --(1) Primary --(2) Tabelas --(3) Indices drop database db_name

go CREATE DATABASE db_name ON PRIMARY ( NAME = dbname_primaryfile, FILENAME = 'c:\dbs\dbname_primaryfile.mdf', SIZE = 2MB, MAXSIZE = 2MB), FILEGROUP Tabelas ( NAME = db_name_tabelas_1, FILENAME = 'c:\dbs\dbname_tabelas_1.ndf', SIZE = 1MB, MAXSIZE = 10MB, FILEGROWTH = 512KB), ( NAME = db_name_tabelas_2, FILENAME = 'c:\dbs\dbname_tabelas_2.ndf', SIZE = 1MB, MAXSIZE = 10MB, FILEGROWTH = 512KB), FILEGROUP Indices ( NAME = db_name_indices_1, FILENAME = 'c:\dbs\dbname_indices_1.ndf', SIZE = 1MB, MAXSIZE = 10MB, FILEGROWTH = 512KB) --Comentrio---O default filegroup o PRIMARY, logo quando criar um objecto e no especificar a localizao ele ser criado no PRIMARY. -- boa prtica no criar objectos no primary filegroup. Este contm todos os system objects da base de dados. ---Como que o SqlServer preenche os ficheiros contidos num filegroup (quando este contm mais do que um ficheiro)? -- usada uma estratgia proporcional para todos os ficheiros de um filegroup, ou seja: --O SqlServer no escreve num ficheiro at ficar completo passando depois a escrever no seguinte. -- medida que os dados so escritos no filegroup, escolhido um ficheiro de forma a que a percentagem de espao livre seja idntica para todos os ficheiros contidos no filegroup. --Desta forma, todos os ficheiros ficaro completos ao mesmo tempo. --Quando todos os ficheiros esto completos o processo muda. --Quando todos os ficheiros estiverem completos, o SqlServer expande automaticamente (se estiver configurado) apenas o primeiro ficheiro. --Quando este estiver completo, expande automaticamente o segundo, e assim sucessivamente. use db_name go --Verificar qual o default filegroup. --SqlServer 2000 SqlServer 2005 select * from sys.sysfilegroups select * from sys.filegroups

--Status: -- 8 -> Readonly -- 16 -> Default

is_default 1 -> Default

/* CREATE TABLE table_name ( { < column_definition > | < table_constraint > } [ ,...n ] ) < column_definition > ::= { column_name data_type } [ { DEFAULT constant_expression | [ IDENTITY [ ( seed , increment ) ] ] } ] [ ROWGUIDCOL ] [ < column_constraint > [ ...n ] ] < column_constraint > ::= [ CONSTRAINT constraint_name ] { [ NULL | NOT NULL ] | [ PRIMARY KEY | UNIQUE ] | REFERENCES ref_table [ ( ref_column ) ] [ ON DELETE { CASCADE | NO ACTION } ] [ ON UPDATE { CASCADE | NO ACTION } ] } < table_constraint > ::= [ CONSTRAINT constraint_name ] { [ { PRIMARY KEY | UNIQUE } { ( column [ ,...n ] ) } ] | FOREIGN KEY ( column [ ,...n ] ) REFERENCES ref_table [ ( ref_column [ ,...n ] ) ] [ ON DELETE { CASCADE | NO ACTION } ] [ ON UPDATE { CASCADE | NO ACTION } ] } */ -------------------------------------------------------Criar uma tabela sem especificar a sua localizao------------------------------------------------------create table t1( codigo int constraint pk_t1 primary key, nome varchar(20)) --Verificar a localizao da tabela sp_help t1 --Quando se cria uma constraint "primary key", criado automaticamente um "unique index" --A tabela e o ndice associado primary key esto localizados no primary filegroup ---------------------------------------------------------------------Criar uma tabela especificando o filegroup onde a queremos criar----------------------------------------------------------------------Neste caso a localizao da tabela e do ndice o filegroup Tabelas drop table t1 create table t1( codigo int constraint pk_t1 primary key, nome varchar(20))

on Tabelas sp_help t1 --A tabela e o ndice associado primary key esto localizados no filegroup Tabelas --Criar uma tabela especificando uma localizao diferente para a tabela e para o ndice. drop table t1 create table t1( codigo int constraint pk_t1 primary key on Indices, nome varchar(20)) on Tabelas sp_help t1 --A tabela e o ndice associado primary key esto localizados no filegroup Indices... --...apesar de termos explicitamente definido que queriamos a tabela no filegroup Tabelas --No h problema algum. A questo que por defeito, o ndice associado primary key clustered. --Clustered Index Structure --Clustered Indexes so B-trees. Cada pgina na B-tree index um "index node". --O "top node" da B-tree chamado "root node". --O nvel de ns inferior contm "leaf nodes". --Quaisquer nveis de ns entre "root node" e os "leaf nodes" contm "intermediate nodes". --Num clustered index, os "leaf nodes" contm as "data pages" da tabela. --Os root e intermediate nodes apenas contm "index pages". --Cada "index page" engloba "index rows" que no so mais do que o conjunto definido por ("key value" + apontador) para um "intermediate node" ou uma "data row" de um "leaf node" --As pginas em cada nvel da B-Tree so listas duplamente ligadas. --Non-Clustered Index Structure --Non-Clustered Indexes, assim como os Clustered Indexes so B-trees, com a seguinte diferena. --As "data rows" no fazem parte da estrutura do ndice, ou seja, o "leaf level" contm "index pages" e no "data pages" --Vamos criar a tabela e posteriormente acrescentar a primary key. drop table t1 create table t1( codigo int, nome varchar(20)) on Tabelas sp_help t1 --Neste momento a tabela tem os dados no filegroup Tabelas /* ALTER TABLE table_name { [ ALTER COLUMN column_name {DROP DEFAULT | SET DEFAULT constant_expression | IDENTITY [ ( seed , increment ) ] } | ADD { < column_definition > | < table_constraint > } [ ,...n ] | DROP { [ CONSTRAINT ] constraint_name

| COLUMN column } ] } < column_definition > ::= { column_name data_type } [ [ DEFAULT constant_expression ] | IDENTITY [ ( seed , increment ) ] ] [ROWGUIDCOL] [ < column_constraint > ] [ ...n ] ] < column_constraint > ::= [ NULL | NOT NULL ] [ CONSTRAINT constraint_name ] { | { PRIMARY KEY | UNIQUE } | REFERENCES ref_table [ (ref_column) ] [ ON DELETE { CASCADE | NO ACTION } ] [ ON UPDATE { CASCADE | NO ACTION } ] } < table_constraint > ::= [ CONSTRAINT constraint_name ] { [ { PRIMARY KEY | UNIQUE } { ( column [ ,...n ] ) } | FOREIGN KEY ( column [ ,...n ] ) REFERENCES ref_table [ (ref_column [ ,...n ] ) ] [ ON DELETE { CASCADE | NO ACTION } ] [ ON UPDATE { CASCADE | NO ACTION } ] } */ --Adicionar a primary key alter table t1 add constraint pk_t1 primary key(codigo) on Indices --Msg 8111, Level 16, State 1, Line 1 --Cannot define PRIMARY KEY constraint on nullable column in table 't1'. --Verificamos que quando se definia a contraint juntamente com o comando create table, o(s) campo(s) associado(s) primary key ficava automaticamente "not null" --Temos de efectuar um passo adicional alter table t1 alter column codigo int not null alter table t1 add constraint pk_t1 primary key(codigo) on Indices sp_help t1 --Verificamos que os dados foram movidos para o filegroup do ndice. --Se a tabela tivesse muitos registos o alter table poderia demorar bastante tempo a executar --Vamos criar uma primary key nonclustered drop table t1 create table t1( codigo int constraint pk_t1 primary key nonclustered on Indices, nome varchar(20)) on Tabelas sp_help t1 --Agora j temos os dados no filegroup Tabelas e o ndice no filegroup Indices. -----------------------------------Alterao do Default Filegroup-----------------------------------

--Se quiserem criar vrias tabelas... --E quiserem coloc-las todas no mesmo filegroup... --E quiserem colocar os ndices nesse mesmo filegroup... --E o filegroup que querem no o PRIMARY... --Ento alterem o DEFAULT filegroup --Especificar que o DEFAULT FILEGROUP o grupo Tabelas. ALTER DATABASE db_name MODIFY FILEGROUP Tabelas DEFAULT --Agora todos os objectos criados tero por defeito o filegroup Tabelas select * from sys.filegroups drop table t1 create table t1( codigo int constraint pk_t1 primary key nonclustered on Indices, nome varchar(20)) sp_help t1 --------------------------------Como criar novos filegroups-------------------------------/* ALTER DATABASE database_name { <add_or_modify_files> | <add_or_modify_filegroups> | <set_database_options> | MODIFY NAME = new_database_name | COLLATE collation_name } [;] <add_or_modify_files>::= { ADD FILE <filespec> [ ,...n ] [ TO FILEGROUP { filegroup_name | DEFAULT } ] | ADD LOG FILE <filespec> [ ,...n ] | REMOVE FILE logical_file_name | MODIFY FILE <filespec> } <filespec>::= ( NAME = logical_file_name [ , NEWNAME = new_logical_name ] [ , FILENAME = 'os_file_name' ] [ , SIZE = size [ KB | MB | GB | TB ] ] [ , MAXSIZE = { max_size [ KB | MB | GB | TB ] | UNLIMITED } ] [ , FILEGROWTH = growth_increment [ KB | MB | GB | TB| % ] ] [ , OFFLINE ] ) <add_or_modify_filegroups>::= { | ADD FILEGROUP filegroup_name | REMOVE FILEGROUP filegroup_name | MODIFY FILEGROUP filegroup_name { <filegroup_updatability_option> | DEFAULT | NAME = new_filegroup_name

} } */ ALTER DATABASE db_name ADD FILEGROUP NovoFileGroup --A criao de um filegroup no implica a criao de ficheiros. -- possvel criar objectos num filegroup que no tenha nenhum ficheiro associado... --...mas no possvel associar-lhes dados --Exemplo: create table t2( a int) on NovoFileGroup --A tabela foi criada. insert into t2 values(1) --Msg 622, Level 16, State 3, Line 1 --The filegroup "NovoFileGroup" has no files assigned to it. Tables, indexes, text columns, ntext columns, and image columns cannot be populated on this filegroup until a file is added. --Criar novos ficheiros e associ-los ao novo filegroup ALTER DATABASE db_name ADD FILE ( NAME = db_name_novofilegroup_1, FILENAME = 'c:\dbs\dbname_novofilegroup_1.ndf', SIZE = 1MB, MAXSIZE = 10MB, FILEGROWTH = 512KB), ( NAME = db_name_novofilegroup_2, FILENAME = 'c:\dbs\dbname_novofilegroup_2.ndf', SIZE = 1MB, MAXSIZE = 10MB, FILEGROWTH = 10%) TO FILEGROUP NovoFileGroup --J possvel inserir informao insert into t2 values(1) --Temos ento uma tabela com um registo, contida no filegroup NovoFileGroup --Esse filegroup tem dois ficheiros. --Os registos da tabela (como visto anteriormente) esto em "data pages" que se encontram num dos dois ficheiros. S no sabemos qual deles . --O registo foi inserido numa "data page" contida ou no ficheiro db_name_novofilegroup_1, ou db_name_novofilegroup_2 --Neste caso particular, como no havia informao (inserimos agora o 1 registo), o SqlServer escolheu db_name_novofilegroup_2 que foi o ltimo ficheiro especificado. -- medida que vamos preenchendo as data pages com informao, o SqlServer vai seleccionando um dos ficheiros, de acordo com o espao livre que tiverem --------------------------Eliminar um data file-------------------------ALTER DATABASE db_name REMOVE FILE db_name_novofilegroup_1 --The file 'db_name_novofilegroup_1' has been removed ALTER DATABASE db_name REMOVE FILE db_name_novofilegroup_2

--Msg 5042, Level 16, State 1, Line 1 --The file 'db_name_novofilegroup_2' cannot be removed because it is not empty. --Comprova-se que os dados estavam numa pgina contida no ficheiro db_name_novofilegroup_2, logo, no deve ser possvel elimin-lo. --Se o objectivo mesmo eliminar o ficheiro (e perder a informao)... --Temos que eliminar a tabela (no basta apagar a informao) delete from t2 ALTER DATABASE db_name REMOVE FILE db_name_novofilegroup_2 --Msg 5042, Level 16, State 1, Line 1 --The file 'db_name_novofilegroup_2' cannot be removed because it is not empty. --Concluimos que podemos criar uma tabela num filegroup que no tenha ficheiros associados... --No entanto, no podemos eliminar ficheiros de filegroups se estes alguma vez tiveram "data pages" com informao. --Assim sendo, temos de eliminar a tabela drop table t2 ALTER DATABASE db_name REMOVE FILE db_name_novofilegroup_2 --The file 'db_name_novofilegroup_2' has been removed. --------------------------Eliminar um filegroup-------------------------ALTER DATABASE db_name REMOVE FILEGROUP NovoFileGroup ---------------------------------------Alterar ficheiros da base de dados--------------------------------------select * from sys.database_files --O ficheiro db_name_tabelas_1 tem tamanho de 128*8KB = 1MB, e cresce em incrementos de 64KB*8KB = 512KB --Alterar estes valores para: --Tamanho: 2.5MB --Incremento: 20% ALTER DATABASE db_name MODIFY FILE ( NAME = db_name_tabelas_1, SIZE = 2560KB, FILEGROWTH = 20%) select * from sys.database_files --Consideraes: --No possvel especificar SIZE = 2.5MB, temos de usar valoes inteiros, da os 2560KB --Os parmetros no especificados mantm-se (MAXGROWTH, por exemplo) --Podemos alterar o nome lgico do ficheiro... ALTER DATABASE db_name MODIFY FILE ( NAME = db_name_tabelas_1, NEWNAME = db_name_tabelas_1_novo_nome) --...e at o nome fsico ALTER DATABASE db_name MODIFY FILE ( NAME = db_name_tabelas_1_novo_nome, FILENAME = 'c:\dbs\dbname_tabelas_1_novo_nome.ndf')

--The file "db_name_tabelas_1_novo_nome" has been modified in the system catalog. The new path will be used the next time the database is started. --Mas temos que reiniciar a base de dados para as alteraes surtirem efeito --Mudar de contexto use master --Colocar BD offline ALTER DATABASE db_name SET OFFLINE --...e online ALTER DATABASE db_name SET ONLINE --Msg 5120, Level 16, State 5, Line 1 --Unable to open the physical file "c:\dbs\dbname_tabelas_1_novo_nome.ndf". Operating system error 2: "2(The system cannot find the file specified.)". --Msg 945, Level 14, State 2, Line 1 --Database 'db_name' cannot be opened due to inaccessible files or insufficient memory or disk space. See the SQL Server errorlog for details. --Msg 5069, Level 16, State 1, Line 1 --ALTER DATABASE statement failed. --O problema que ns dissemos ao SqlServer que o ficheiro com o nome lgico db_name_tabelas_1_novo_nome... --... aponta para "c:\dbs\dbname_tabelas_1_novo_nome.ndf", mas o ficheiro no existe! --Vejamos: (Activar SQLDMO e autenticar no servidor) !!dir \\gandalf\dbs\dbname*.* /* O volume na unidade \\gandalf\dbs no tem nome O nmero de srie do volume 148C-81B9 Directrio de \\gandalf\dbs 04-03-2006 04-03-2006 04-03-2006 04-03-2006 16:03 1.048.576 dbname_indices_1.ndf 16:03 2.097.152 dbname_primaryfile.mdf 16:03 2.621.440 dbname_tabelas_1.ndf 16:03 1.048.576 dbname_tabelas_2.ndf 4 ficheiro(s) 6.815.744 bytes 0 Dir(s) 96.735.670.272 bytes livres

*/ --Temos ento de mudar o nome do ficheiro !!move \\gandalf\dbs\dbname_tabelas_1.ndf \\gandalf\dbs\dbname_tabelas_1_novo_nome.ndf !!dir \\gandalf\dbs\dbname*.* /* O volume na unidade \\gandalf\dbs no tem nome O nmero de srie do volume 148C-81B9 Directrio de \\gandalf\dbs 04-03-2006 16:03 1.048.576 dbname_indices_1.ndf

04-03-2006 04-03-2006 04-03-2006

16:03 2.097.152 dbname_primaryfile.mdf 16:03 2.621.440 dbname_tabelas_1_novo_nome.ndf 16:03 1.048.576 dbname_tabelas_2.ndf 4 ficheiro(s) 6.815.744 bytes 0 Dir(s) 96.735.285.248 bytes livres

*/ --...e agora ALTER DATABASE db_name SET ONLINE --Command(s) completed successfully.

-- ****************************************************************** ----------------------------------------------Como obter informao sobre os objectos?---Sem usar sp_help... ----------------------------------------------Conceitos: ---Data Pages --Cada pgina so 8KB --A pgina inclui um header de 96B com informao sobre o n de pgina, o tipo, o espao livre, e a "allocation unit ID" do objecto qual a pgina pertence --Os restantes 8096B so divididos em 8060B para dados, e 36B para page offset --Extents --Um extent so 8 pginas. --Podem ser uniformes (todas as pginas pertencem ao mesmo objecto) --Ou mistos (cada pgina pode pertencer a um objecto diferente) --Cada tabela ou ndice tem uma linha na "catalog view" sys.system_internals_allocation_units --Essa linha unicamente identificada por um container ID. --O container ID (container_id) relacionado [um-para-um] com (partition_id) na catalog view sys.partitions --sys.partitions tem uma linha por cada partio numa tabela ou ndice -- esta relao que permite mapear os dados com as allocation units. --Obter informao sobre o objecto: select * from sys.tables where name = 't1' --ou select * from sys.objects where name = 't1' --No meu caso, a tabela t1 identificada por object_id = 181575685 --Parties select * from sys.partitions where object_id = 181575685 --ou... select * from sys.partitions where object_id = (select object_id from sys.tables where name = 't1') --partition_id object_id index_id partition_number hobt_id rows --72057594038976512 181575685 0 1 72057594038976512 0

--72057594039042048 181575685 2 1 72057594039042048 0 --H duas parties. Uma da tabela e outra do ndice da primary key select from where and * sys.system_internals_allocation_units a, sys.partitions b a.container_id = b.partition_id b.partition_id in (select partition_id from sys.partitions where object_id = (select object_id from sys.tables where name = 't1')) --ou... select * from sys.system_internals_allocation_units a, sys.partitions b, sys.tables c where a.container_id = b.partition_id and b.object_id = c.object_id and c.name = 't1' --Desta forma podemos concluir que a tabela t1 est criada no filegroup n2 --E o ndice no filegroup n3 --Verifiquemos que est corecto: select * from sys.filegroups

You might also like