konto usunięte

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Załóżmy że w bazie danych zostały zdefiniowane kolumny typach NUMBER (bez precyzji i skali) oraz VARCHAR(300). Okazało się, że tak zdefiniowane kolumny zabierają niepotrzebnie dużo miejsca bo faktycznie wszystkie dane w nich zawarte mogłyby się zmieścić w typach NUMBER(10) oraz VARCHAR(20).

Jeśli wykonam polecenie:

ALTER TABLE BLA
MODIFY(COLUMN BLE NUMBER(10));

To czy:

- zachowają się dane już obecne w kolumnie i czy można taką operację w ogóle na niepustej kolumnie wykonać?
- Jeśli znajdą się wiersze niemieszczące się w tym przedziale czy ORACLE nie dopuści do zmiany?
- Czy wcześniej nadane wartości domyślne kolumn zostaną zachowane?
- Czy wcześniej założone indeksy zostaną zachowane?
- Czy klucze publiczne, obce, unikalne, zostaną zachowane?
- Czy informacja o tym czy kolumna może być NULL zostaną zachowane?
- Czy wszystkie więzy integralności dotyczące tej kolumny zostaną zachowane?
Damian L.

Damian L. Architekt IT

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Skąd pomysł, że "wielkość" stringa o długości 10 w kolumnie zdefiniowanej jako varchar2(1000) i varchar2(10) jest inna? Chyba, że nie rozumiem o jakiej wielkości mówisz. Różnica jest w aplikacjach klienckich czy PL/SQL, bo trzeba stworzyć zmienną która może te potencjalne 1000 znaków pomieścić.

A na pytania bardzo łatwo mogłeś sobie odpowiedzieć sam robiąc to o czym napisałeś, tylko czy jest sens? ;)Damian L. edytował(a) ten post dnia 19.10.12 o godzinie 20:28
Wojciech Muszyński

Wojciech Muszyński Tworzenie aplikacji
bazodanowych
(Oracle, APEX,
Access)

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Kod modyfikujący kolumnę jest nieco inny:

alter table bla modify ble varchar2(20);

Co do zachowania Oracle to najlepiej samemu to sprawdzić.
Utworzyć tablice testową i zobaczyć co się stanie.

odpowiedni kod:

-- utworzenie tabeli
create table bla
( ble varchar2 (50));

-- utworzenie indeksu
create index bla_i
on bla (ble ) ;

-- wprowadzenie 25 znaków
insert into bla(ble) values ('1234567890123456789012345');

-- sprawdzenie długości najdłuższego elementu w tabeli:
select max(length(ble)) maks_dlugosc_ble_w_bla from bla;


-- modyfikacja do 20 znaków
alter table bla modify ble varchar2(20);



Warto spróbować samemu.

(dla leniwych:
pojawi się błąd:
ORA-01441: cannot decrease column length because some value is too big)

W przypadku modyfikacji do 30 znaków operacja zostanie zakończona sukcesem.

indeks i inne elementy/właściwości "pochodne" zostaną nie zmienione).

I jeszcze jedna ważna informacja:
Ilość miejsca w zajętego w bazie po zamianie pola varchar2(300) na varchar2(20) nie ulegnie zmianie!

http://andrzejklusiewicz.blogspot.com/2010/11/kurs-ora...
Varchar2(L)

Dane tego typu zajmują dokładnie tyle miejsca ile zostanie przypisanych znaków. Parametr L określa maksymalną ilość znaków. L musi być mniejsze od 4000..
Wojciech Muszyński edytował(a) ten post dnia 19.10.12 o godzinie 20:41

konto usunięte

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Wojciech Muszyński:
I jeszcze jedna ważna informacja:
Ilość miejsca w zajętego w bazie po zamianie pola varchar2(300) na varchar2(20) nie ulegnie zmianie!

http://andrzejklusiewicz.blogspot.com/2010/11/kurs-ora...
Varchar2(L)

Dane tego typu zajmują dokładnie tyle miejsca ile zostanie przypisanych znaków. Parametr L określa maksymalną ilość znaków. L musi być mniejsze od 4000..

I to samo dotyczy typu NUMBER.Łukasz Pluta edytował(a) ten post dnia 19.10.12 o godzinie 21:28
Maciej W.

Maciej W. Oracle developer

Temat: ORACLE - konsekwencje zmiany długości kolumny.

1. Co to za typ VARCHAR? (Oracle zaleca używanie VARCHAR2 zamiast VARCHAR)
2. Zmiana "w górę" jest szybka i w miarę transparentna: alter i raz dwa mamy redefiniowaną tabelę.
3. Powiązania i relacje, AFAIK, opierają się na wartościach a nie definicji limitów tych wartości (czyli będą nadal działać)
4. Zmiana "w dół" może być bolesna... z varchar2(20) łatwo przejdziesz na varchar2(30) ale w drugą stronę możliwe są komplikacje.
5. Wartość w nawiasie (precyzja typu NUMBER czy VARCHAR2) to taki limit, ile tam można max upchać. To wcale nie oznacza, że VARCHAR2(4000 BYTES) zajmie 4000 bajtów na dysku. Polecam użycie "select dump(...) from tabela".
6. Liczby w Oracle są zapisywane dość specyficznie... najłatwiej chyba je przyrównać do stringa z cyferkami każda w oddzielnym bajcie (bajty są tu 4-bitowe) oraz dodatkową informacją o położeniu przecinka.
Oczywiście odsyłam do oracle.com i tamtejszej dokumentacji...

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Wojciech Muszyński:
Co do zachowania Oracle to najlepiej samemu to sprawdzić.

Dlaczego? ;)
Wojciech Muszyński

Wojciech Muszyński Tworzenie aplikacji
bazodanowych
(Oracle, APEX,
Access)

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Wojciech T.:
Dlaczego? ;)

1. Z ciekawości.
2. Bo w ten sposób można się najwięcej nauczyć.
3. Bo nabiera się doświadczenia w pracy z narzędziami, z których się korzysta.
Andrzej W.

Andrzej W. Oracle Database
Developer

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Ja osobiście bym zauważył, iż zwiększenie rozmiaru kolumny np. VARCHAR2(20) do VARCHAR2(4000) samo w sobie jest szybkie i bezproblemowe, jednak update dodający dużą ilość danych dla takiej kolumny może wywołać row migration, a co za tym idzie pogorszenie wydajności indeksów.
Wojciech Muszyński

Wojciech Muszyński Tworzenie aplikacji
bazodanowych
(Oracle, APEX,
Access)

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Możliwe są też inne negatywne konsekwencje. Np. zwiększone zużycie pamięci operacyjnej przez programy w PL/SQL. Fakt, że przy dzisiejszych pamięciach trzeba się postarać, aby to był problem.

Ale można wymyślić sobie np. następujący scenariusz:

Tworzymy tabelę z 100 kolumnami varchar2(20).
Zamieniamy na 100x varchar2(4000).

Tworzymy w PL/SQL typ rekordowy na podstawie tabeli (nazwa_tabeli%rowtype).
Następnie tworzymy kolekcję opartą na tym typie.

Przy odpowiednio dużej liczbie rekordów w kolekcji może to powodować problemy.

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Ale można wymyślić sobie np. następujący scenariusz:

Tworzymy tabelę z 100 kolumnami varchar2(20).
Zamieniamy na 100x varchar2(4000).

Tworzymy w PL/SQL typ rekordowy na podstawie tabeli (nazwa_tabeli%rowtype).
Następnie tworzymy kolekcję opartą na tym typie.

Przy odpowiednio dużej liczbie rekordów w kolekcji może to powodować problemy.

A ta baza stoi na 386 z wyłączonym turbo...
Andrzej W.

Andrzej W. Oracle Database
Developer

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Wojciech T.:
Ale można wymyślić sobie np. następujący scenariusz:

Tworzymy tabelę z 100 kolumnami varchar2(20).
Zamieniamy na 100x varchar2(4000).

Tworzymy w PL/SQL typ rekordowy na podstawie tabeli (nazwa_tabeli%rowtype).
Następnie tworzymy kolekcję opartą na tym typie.

Przy odpowiednio dużej liczbie rekordów w kolekcji może to powodować problemy.

A ta baza stoi na 386 z wyłączonym turbo...

Bardziej chodzi o pamięć, taka kolekcja może zabrać od OS-a nieprzewidzianą wcześniej ilość pamięci, obiekty PL/SQL-owe nie podlegają limitom bazy co do zużycia pamięć.
Maciej W.

Maciej W. Oracle developer

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Wojciech Muszyński:
Możliwe są też inne negatywne konsekwencje. Np. zwiększone zużycie pamięci operacyjnej przez programy w PL/SQL. Fakt, że przy dzisiejszych pamięciach trzeba się postarać, aby to był problem.
Sprawa jest dużo bardziej złożona. Typ VARCHAR2 w PL/SQL to typ dynamiczny, który zajmuje tyle, ile musi... prawie... no niezupełnie... jak się okazuje po głębszej analizie to do pewnego rozmiaru Oracle alokuje z góry miejsce a powyżej pewnej granicy (2000 chyba) typ zaczyna być dynamiczny. Tak więc (zakładając, że podana przeze mnie wartość 2000 jest poprawna) definiując typ varchar2(1999) zajmujemy co najmniej 1999 bajtów a varchar2(2000) zajmie ich tylko kilka => oszczędzimy miejsce w pamięci! W ten sposób możemy powiększyć rozmiar docelowy zmiennych i nagle zaobserwować, że przybyło nam jakimś nieznanym sposobem 16GB wolnego miejsca w RAMie :D
O problemy z pamięcią nie trzeba się tak bardzo starać ale na palcach ręki mogę policzyć ile razy miałem poważne problemy z alokacją pamięci w pl/sql - duuuużo częściej zdarza się to z alokacją buforów, transakcji, wyciekiem obiektów niż z właściwą alokacją obiektów.
Jak bym się miał czegoś obawiać to raczej zbliżenia się do magicznego limitu 4000, 8000 lub 32767 albo też nadmiernego upychania danych w komórkach (jeśli user może pchać na maxa tekst do kolumny to możemy skończyć z kolumną typu CLOB w której jakiś niepoprawny student-programista wrzuci wartość CSV).
Andrzej Wieczorek:
Bardziej chodzi o pamięć, taka kolekcja może zabrać od OS-a nieprzewidzianą wcześniej ilość pamięci, obiekty PL/SQL-owe nie podlegają limitom bazy co do zużycia pamięć.
Nie? SGA/PGA po coś zostały stworzone. "Unable to allocate XXX bytes of memory" czy jakoś tak brzmi ten błąd. Warto zwrócić uwagę na znaczenie suffiksów _MAX i _TARGET - ponieważ one mogą określać odgóry limit alokacji pamięci.
Andrzej W.

Andrzej W. Oracle Database
Developer

Temat: ORACLE - konsekwencje zmiany długości kolumny.

A można jakiś przykład do tej pierwszej części. Próbowałem sprawdzić o ile zwiększy się zużycie PGA dla nowej sesji przy kolekcji zawierającej elementy VARCHAR2(400) oraz VARCHAR2(4000) i za każdym razem uzyskiwałem podobne rezultaty. W obu przypadkach ilość pamięci zależała jedynie od długości tekstu który przypisywałem do obiektów, tak więc wynikało by z tego że również poniżej 2000 znaków typ jest dynamiczny.

Jeśli chodzi o ograniczenia bazy co do pamięci SGA to zgadzam się, że baza ich nie przekroczy, jednak parametr PGA_AGGREGATE_TARGET nie jest ograniczeniem twardym i nie ma przeciwwskazań by go przekroczyć. Bardziej służy on do automatycznego przydzielania pamięci dla obszarów sortowania, hashowania itp.
Maciej W.

Maciej W. Oracle developer

Temat: ORACLE - konsekwencje zmiany długości kolumny.

Andrzej Wieczorek:
A można jakiś przykład do tej pierwszej części. Próbowałem sprawdzić o ile zwiększy się zużycie PGA dla nowej sesji przy kolekcji zawierającej elementy VARCHAR2(400) oraz VARCHAR2(4000) i za każdym razem uzyskiwałem podobne rezultaty. W obu przypadkach ilość pamięci zależała jedynie od długości tekstu który przypisywałem do obiektów, tak więc wynikało by z tego że również poniżej 2000 znaków typ jest dynamiczny.
https://forums.oracle.com/forums/thread.jspa?threadID=9...
i askTom
http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P1...

"a varchar2 less then 2000 bytes will allocate a fixed amount of memory" - więc dobrze chyba pamiętałem limit :)

Pozdrawiam
Maciej Wakuła
Maciej W.

Maciej W. Oracle developer

Temat: ORACLE - konsekwencje zmiany długości kolumny.

W zasadzie należałoby jeszcze zaznaczyć, że zmiana wielkości VARCHAR2(1999) na VARCHAR2(2000) może przynieść negatywne skutki wydajnościowe ponieważ operacje wykonujemy bardziej dynamicznie - doklejanie po znaku może się okazać dość wolne :D



Wyślij zaproszenie do