Temporary Tablespace Alanı Hakkında
Oracle veritabaninda büyük ölçekteki sort islemleri için sunucumuzun hafizasi (RAM) yetersiz kaldiginda, bu islemlerin sabit disk üzerinde gerçeklestirilmesi gerekmektedir. Bu islemlerin sabit disk üzerinde gerçeklestirildigi Oracle veritabani alanina temporary tablespace denilir. Temporary tablespace ‘in diger tablespace ‘lerden farki, mantiksal anlamda datafile degil tempfile kullanmasidir. O nedenle temporary tablespace ‘e yeni bir datafile eklenecegi zaman komut içersinde datafile degil, “tempfile” ifadesini kullaniriz.
Veritabanimizin temporary tablespace alanini resize edemedigimiz durumlarda veya yeni bir temporary tablespace alanina ihtiyacimiz duydugumuzda asagidaki yönergeleri takip ederek yeni bir temporary tablespace alani olusturabiliriz. Bu konuda dikkat etmemiz gereken husus, default temporary tablespace alani kullanicilar tarafindan aktif olarak sort v.b islemler kullanildigindan, eski temporary tablespace alanini drop etmeden önce yeni temporary tablespace ‘in olusturulmasinin gerekliligidir. Simdi sirasiyla yeni temporary tablespace alanini olusturup, eksisini sistemden kaldiralim.
- Öncelikle kendimize yeni bir temporary tablespace alani olusturulalim. Tablespace içersindeki datafile ‘in büyüklügünü ihtiyaciniza göre ayarlayabilirsiniz. Olusturacagimiz yeni tablespace alani için asagida 16Gb ‘lik bir datafile ekledim fakat, büyük ölçekte kayitlara sahip tablolar tutuyorsaniz buna göre daha genis temporay tablespace kullanmaniz gerekebilir.
SQL> create temporary tablespace YENITEMP tempfile '/oracle/data/yenitemp1.dbf' size 16384M autoextend on next 512M maxsize 32767M;
- Yeni temporary tablespace alanini veritabanina ekledik. Simdi yeni ekledigimiz temporary tablespace alanini, default tablespace olarak atayalim. Bundan sonra yapilacak olan sort islemleri artik yeni olusturdugumuz tablespace ‘de gerçeklestirilecek.
- Yeni default temporary tablespace alanimizi kullanmaya basladik, artik eski temporary tablespace alanini drop etmeye haziriz.
SQL> alter database default temporary tablespace YENITEMP;
SQL> drop tablespace ESKITEMP including contents and datafiles;
Tebrikler.
boraovali.com
Table Partition oluşturma
Gittikçe büyüyen ve data yükü artan tablolar üzerinde sorgu çalıştırmak veya tablo bakımına ait diğer işlemleri gerçekleştirmek zamanla çeşitli problemlere sebep olmaktadır. Problemleri ortadan kaldırmanın kullanışlı ve etkili yollarından birisi tabloyu bütünlüğünü koruyacak şekilde parçalara ayırmak ve ilgili işlemleri sadece gerekli olan parçalar üzerinde yapmaktır. Partitioning kavramı bahsedilen bu işlemleri gerçekleştirebileceğimiz bir yapı sunmaktadır, tablonun bütünlüğü korunarak üzerindeki işlemlerin daha hızlı gerçekleştirilebileceği parçalara ayrılır.
Partitioning kavramı üzerinde bahsedilmesi gereken ayrıntılarla devam etmek istiyorum, tablo üzerinde partition oluşturmak tablonun genel bütünlüğünü bozmayacağından tablo üzerinde çalıştırılan sorgularda değişiklik yapmaya gerek yoktur. Bu nedenle işleyen sistemler üzerinde uygun partition metodunu seçerek kullanılan sorguları değiştirmeden partitioning işlemi gerçekleştirilebilir. Aynı zamanda partitioning metoduna bağlı olarak ayrılan her parçanın kendi ismi ile sadece ayrılan parçaya ait işlemler de gerçekleştirilebilir. Parçalar ayrı ayrı drop/truncate edilebilir, üzerlerinde farklı bir index oluşturulabilir. Partitioning in diğer avantajı ise küçük parçalar ile uğraştığından sorgularda çok daha performanslı olmasıdır. Ayrıca partitioning yapılmamış bir tabloya sonradan partitioning yapıldığında tablo üzerinde çalışan sorgu ve DML lerde herhangi bir değişikliğe gerek olmaması bu yapının oldukça esnek olarak kullanılmasını sağlamaktadır.
Partition lara ayrılan bir tabloda herbir satır tek bir parçaya ait olabilir, satırın ait olacağı parçanın belirlenmesi için partition key kullanılır. Partition key null alabilen bir değerden de oluşabilir.
Yukarda bahsettiğim gibi bazı işlemlerin gerçeklenebilmesi tablo üzerindeki partitioning metoduna bağlıdır. Partitioning metodlarını daha yakından inceleyecek olursak:
Oracle tarafından 4 farklı partitioning yöntemi desteklenmektedir:
· Range Partitioning.
· List Partititoning
· Hash Partitioning
· Composite Partitioning
Range Partitioning Metodu
Range metodu ile partition işleminde partition keyi üzerinde belirli aralıklardaki değerlere göre parçalar oluşturulur. Örneğin tablo üzerinde yılların tutulduğu bir alana sahibiz, bu alanı partition key olarak belirleyip yıllara göre parçalar oluşturabilir, artık kullanmayacağımız yılların datalarını direk ilgili partitionu kullanarak drop/truncate edebilir veya belirli bir yıla göre sorgularımızı gerçekleştirebiliriz. Veya illere göre verilerin tutulduğu bir tabloda il kolonu üzerinde partition yapılarak sadece ilgilenilen ilin datası ile işlemler yapılabilir. Partitionda less than ile belirtilen değerden daha küçük olan aralık alınır, MAXVALUE değeri ile ise bir üst sınır belirlenir, belirlenen en büyük değerin dışına çıkan ve null olan değerler bu parça içerisine dahil olacaklardır.
Number tipe gore range partition örneği:
CREATE TABLE emp (
empno NUMBER(4),
ename VARCHAR2(30),
sal NUMBER
)
PARTITION BY RANGE(empno) (
partition e1 values less than (1000) tablespace ts1,
partition e2 values less than (2000) tablespace ts2,
partition e3 values less than (MAXVALUE) tablespace ts3
);
Emp tablosu üzerinde empno keyi kullanılarak bir partition oluşturulmuştur ve 1000 den küçük olan numaralar, 1000-2000 arası olan numaralar ve 2000 den büyük olan numaralar ayrı partitionlarda yer alacaklardır.
Varchar2 string tipe gore partition örneği:
CREATE TABLE emp
( id NUMBER(5) PRIMARY KEY,
name VARCHAR2(50) NOT NULL,
phone VARCHAR2(15),
email VARCHAR2(100) )
PARTITION BY RANGE ( name )
(
PARTITION p1 VALUES LESS THAN ('L') TABLESPACE ts1,
PARTITION p2 VALUES LESS THAN (MAXVALUE) TABLESPACE ts2
)
Date tipe gore range partitioning örneği:
CREATE TABLE t1 (id NUMBER, c1 DATE)
PARTITION BY RANGE (c1)
(PARTITION t1p1 VALUES LESS THAN (TO_DATE('2007-11-01', 'YYYY-MM-DD')),
PARTITION t1p2 VALUES LESS THAN (TO_DATE('2007-12-01', 'YYYY-MM-DD')),
PARTITION t1p3 VALUES LESS THAN (TO_DATE('2008-01-01', 'YYYY-MM-DD')),
PARTITION t1p4 VALUES LESS THAN (MAXVALUE)
);
Hash Partitioning Metodu
Hash partitioning metodu daha çok key olarak range metodundaki gibi bir sınır belirlenemeyecek olan alanlar üzerinde kullanılır, örneğin kimlik numaralarının tutulduğu bir alan üzerinde oluşturulabilir.
Örnekler:
create table emp2 (
empno number(4),
ename varchar2(30),
sal number
)
partition by hash(empno) (
partition e1 tablespace emp1,
partition e2 tablespace emp2,
partition e3 tablespace emp3,
partition e4 tablespace emp4
);
Emp2 tablosu üzerinde farklı tablespaceler kullanılıp empno alanı key olarak kullanılmış ve partition oluşturulmuştur.
create table emp2 (
empno number(4),
ename varchar2(30),
sal number
)
PARTITION BY HASH(empno)
PARTITIONS 3
STORE IN (empts1, empts2, empts3);
Hash Partitioning yönteminde partitionlar round robin mantığı ile oluşturulurlar.
List partitioning
List partitioning methodu ile belirlenen bir liste değerini içerek key üzerinden tablo partitionlara ayrılır.
Örnek:
emp# NUMBER PRIMARY KEY,
ename VARCHAR2(30),
salary NUMBER(8,2),
deptno NUMBER)
PARTITION BY LIST (deptno) ( -- Add list partitioning
PARTITION p10 VALUES (10),
PARTITION p20 VALUES (20),
PARTITION p30 VALUES (30,40));
deptno alanı key olarak kullanılmış ve bu alan için belirlenen değerler için tablo içerisinde parçalar oluşturulmuştur.
List partition için ayrıca listede belirtilmeyen veya listede yer almayıp sonradan eklenebilecek olan değerler ve null değerler için DEFAULT VALUE kullanılır.
CREATE TABLE myemp_work (
emp# NUMBER PRIMARY KEY,
ename VARCHAR2(30),
salary NUMBER(8,2),
deptno NUMBER)
PARTITION BY LIST (deptno) ( -- Add list partitioning
PARTITION p10 VALUES (10),
PARTITION p20 VALUES (20),
PARTITION p30 VALUES (30,40)
PARTITION PDEF VALUES(DEFAULT));
Composite Partitioning
Composite partitioning yöntemi diğer kullanılan yöntemlerin beraber kullanılması ile elde edilen bir yöntemdir. Daha önceden üzerinde partitioning oluşturulmuş olan bir tablodaki parçalar üzerindeki alt parçalar da parçalara ayrılarak verinin içeriğine ve kullanım amacına göre daha kullanışlı bir yapı sağlanabilir.
Range-hash ve range-list metodları birlikte kullanılarak yerine göre avantajlı olan özelliklerinden faydalanılabilir.
Örnek range-hash partitioning yapısı oluşturma:
CREATE TABLE orders(
ord# NUMBER,
orderdate DATE,
prod# NUMBER,
quantity NUMBER)
PARTITION BY RANGE(orderdate)
SUBPARTITION BY HASH(prod#) SUBPARTITIONS 4 -- STORE IN(ts1, ts2, ts3, ts4)
( PARTITION q1 VALUES LESS THAN (TO_DATE('01-APR-2009', 'DD-MON-YYYY')),
PARTITION q2 VALUES LESS THAN (TO_DATE('01-JUL-2009', 'DD-MON-YYYY')),
PARTITION q3 VALUES LESS THAN (TO_DATE('01-OCT-2009', 'DD-MON-YYYY')),
PARTITION q4 VALUES LESS THAN (MAXVALUE)
);
Bahsedilen partitioning methodlarından en uygun olanını seçmek verinin tipine, sunuluş şekline göre değişiklik gösterecektir, bu aşamada hepsinin avantajlı olan kısımlarını göz önünde bulundurarak seçim yapmak gerektiğini göz önünde bulundurmalıyız.
Partition işlemleri yaptığımız tablo üzerinde partitionlara ayrılmış kısımlar hakkında detylı bilgilere aşağıdaki sorguyu kullanarak bakabiliriz.
SELECT * FROM dba_tab_partitions WHERE table_name = '';
Primary Key’i Olmayan Tabloları Listelemek
Veritabanında tablo oluştururken primary key’i oluşturmak zorunlu olmamasına karşın, ilişkisel veritabanı mantığına göre her tabloda olması primary key (birincil anahtar) olmalıdır. İlişkisel veritabanın babası sayılabilecek Edgar F. Codd, “The Relational Model for Database Management” kitabında bunu şu şekilde belirtmiştir:
“İlişkisel Veritabanı Yönetim Sistemi, her tablo için bir birincil anahtar tanımına ihtiyaç duyar.”
Ustanın sözüne uyarak, veritabanımızda primary key’i olmayan tabloları bulmak istersek, şu basit sorguyu kullanabiliriz:
SQL> SELECT t.owner || ‘.’ || t.table_name AS tablename
FROM SYS.dba_tables t
WHERE t.owner NOT IN (’SYS’, ‘SYSMAN’, ‘SYSTEM’, ‘XDB’, ‘WMSYS’, ‘OUTLN’, ‘DBSNMP’ )
AND NOT EXISTS (
SELECT 1
FROM SYS.dba_constraints c
WHERE c.owner = t.owner
AND c.table_name = t.table_name
AND c.constraint_type = ‘P’)
ORDER BY t.owner, t.table_name
Sorguda göreceğiniz üzere özellikle SYS, SYSTEM, SYSMAN gibi Oracle’a ait schemalarındaki tabloları listeden çıkardım, siz bu listeyi daha da geliştirip Oracle ait tüm internal schemaları sorguda filtreleyebilirsiniz veya sorguyu sadece sizin belirlediğiniz schemalar için çalıştırabilirsiniz:
SQL> SELECT t.owner || ‘.’ || t.table_name AS tablename
FROM SYS.dba_tables t
WHERE t.owner IN (’HR’, ‘OE’)
AND NOT EXISTS (
SELECT 1
FROM SYS.dba_constraints c
WHERE c.owner = t.owner
AND c.table_name = t.table_name
AND c.constraint_type = ‘P’)
ORDER BY t.owner, t.table_name
Bir Tablodan Rastgele Kayıt Çekmek
SQL> SELECT * FROM hr.employees ORDER BY DBMS_RANDOM.VALUE;
Bu komut ile HR schemasındaki employees tablosundan çekilen kayıtlar DBMS_RANDOM.VALUE fonksiyonunun ürettiği rastgele sayılara göre sıralanacaktır. Bu yüzden bu sorgunun her çağrılışında dönen kayıtların sırası değişik olacaktır. Siz bu dönen kayıtlardan bir veya daha fazlasını okuyarak istediğiniz rastgele kayıda ulaşabilirsiniz.
Aynı sorguyu MySQL için şu şekilde yazabiliriz:
SQL> SELECT * FROM employees ORDER BY RAND();
Microsoft SQL Server’da RAND() fonksiyonu bulunmasına rağmen, MySQL için yazdığımız sorguyu Microsoft SQL Server’da kullanamıyoruz. Çünkü Microsoft SQL Server’daki RAND() fonksiyonu birden fazla kayıt döndüren bir sorgu içerisinde çağrıldığında random olarak hep aynı sayıyı döndürüyor. Bu yüzden random kayıt seçebilmek için RAND() yerine, NEWID() kullanılması gerekiyor:
SQL> SELECT * FROM employees ORDER BY NEWID();
Bu sorgu random sayı üretmek yerine, her satır/kayıt için unique ID’ler üretiyor ve daha sonra bu ID’lerin içeriğine göre kayıtları sıralayarak döndürüyor. Bu sayede istenilen tablodan rastgele kayıtlar seçilebilmiş oluyor.
Daha hızlı index oluşturmak
Büyük tablolar için indeks yaratılması çoğu zaman dba ‘lar için problemdir çünkü tablodaki kayıt sayısı fazla olduğunda indeksin yaratılmasıda zaman alır. Bu süreçte veritabanı sunucusu indeksin yaratılmasıyla da meşgul olacağından veritabanının genel performansında bir düşüş meydana gelir. Buna göre indeks oluşturken veritabanının performansını düşüren 3 ana unsur bulunmaktadır. Bunlardan ilki yazının başında da belirtiğim gibi indeks yaratılacak tablodaki kayıt sayısıdır. Tablodaki kayıt sayısı arttıkça oluşturmak istediğiniz indeksin büyüklüğüde artar. İkinci unsur, indeksi oluştururken yapılan işlemin kaydının redolog ‘a yazılmasıdır. 10 milyon kayda sahip bir tabloya indeks oluşturmak istediğinizde, işlem süresince 10 milyon kez redolog dosyalarına yapılan işlemin logu da yazılır. Üçüncü dikkat etmemiz gereken unsur indeksi oluşturulurken bu işlem için kaç tane process ‘in meşgul olacağının belirtilmesidir. Sunucu donanımızın kapasitesine göre process sayısını arttırıp azaltabiliriz.
Yukarıda anlattıklarım haricinde daha hızlı indeks oluşturmak için kendinize session bazlı bir sort area size oluşturabilirsiniz. Böylece indeks oluşturlurken sort işlemi sırasında daha fazla memory alanıyla çalışacağınızdan indeksin oluşturulmasıda buna göre kısa zaman alacaktır. Şimdi aşağıda TEST kullanıcısına ait DENEME isimli tablo üzerinde DENEME_IDX isimli bir indeks oluşturalım.
Öncelikle sqlplus ‘a bağlanalım.
sqlplus / as sysdba
Session bazlı kendimize özel bir work area size oluşturalım.
SQL> alter session set workarea_size_policy=manual;
Daha sonra kendimize 40Mb ‘lık bir memory alanı tanımlayalım.
SQL> alter session set sort_area_size=41943040;
Manuel olarak work area size tanımladıktan sonra artık indeksi oluşturmaya hazırız. Bu noktada dikkat etmemiz gereken nokta indeksi oluşturken sistemin kesintiye uğramaması için ONLINE parametresini vermemiz gerektiği. Eğer komut içersinde ONLINE parametresini vermezsek, indeks oluşturlurken tablo kilitli kalacağından çalışan sisteminiz kesintiye uğrayabilir. (ONLINE parametresi sadece Oracle Database Enterprise Edition ile desteklenmektedir.)
SQL> create index test.deneme_idx on test.deneme(kolon1, kolon2) nologging, parallel, online;
İndeksimiz oluşturuldu. Komut içersinde “nologging” parametresini kullanarak yapılan işlemin redolog ‘da kaydının tutulmasını engelledik. “Parallel” parametresiyle index ‘in birden fazla process tarafından oluşturmasını sağladım, böylece yapılan işlemin süresi daha da kısaldı. Bu noktada veritabanından gerçekleştirilecek işlem için kaç tane paralel process açılması gerektiğine veritabanı parametrelerinden “parallel_threads_per_cpu” karar veriyor. Eğer bu parametre üzerinde herhangi bir değişiklik yapmadıysanız Oracle indeks oluşturulması için arka planda 2 adet thread çalıştıracaktır.