Postgresql-zmiana rozmiaru kolumny varchar

Mam pytanie odnośnie komendy ALTER TABLE na naprawdę dużej tabeli (prawie 30 milionów wierszy). Jedną z jego kolumn jest varchar(255) I chciałbym zmienić jej rozmiar na varchar(40). Zasadniczo chciałbym zmienić kolumnę, uruchamiając następujące polecenie:

ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40);

Nie mam problemu, jeśli Proces jest bardzo długi, ale wydaje się, że moja tabela nie jest bardziej czytelna podczas polecenia ALTER TABLE. Czy jest mądrzejszy sposób? Może dodać nową kolumnę, skopiować wartości ze starej kolumny, upuścić starą kolumnę i wreszcie zmienić nazwę nowego?

Każda wskazówka będzie bardzo mile widziana! Z góry dzięki,

Uwaga: używam PostgreSQL 9.0.

Author: Erwin Brandstetter, 2011-10-11

8 answers

Jest opis jak to zrobić w Zmiana rozmiaru kolumny w tabeli PostgreSQL bez zmiany danych. Musisz zhakować dane katalogowe bazy danych. Jedynym sposobem, aby to zrobić oficjalnie jest z ALTER TABLE, i jak już zauważyłeś, że zmiana będzie zablokować i przepisać cały stół podczas jego pracy.

Upewnij się, że zapoznałeś się z sekcją typy znaków dokumentów przed zmianą tej sekcji. Różne dziwne przypadki, o których należy pamiętać. Kontrola długości odbywa się, gdy wartości są zapisywane w wierszach. Jeśli zhakujesz dolny limit, nie zmniejszy to w ogóle rozmiaru istniejących wartości. Mądrze byłoby zrobić skanowanie całej tabeli w poszukiwaniu wierszy, w których długość pola wynosi >40 znaków po dokonaniu zmiany. Musisz wymyśleć jak je obcinać ręcznie - więc masz z powrotem kilka zamków tylko na oversize-bo jak ktoś spróbuje coś uaktualnić w tym wierszu to odrzuci to jako zbyt duże teraz, w momencie gdy idzie do Zapisz nową wersję wiersza. Dla użytkownika następuje wesołość.

VARCHAR jest strasznym typem, który istnieje w PostgreSQL tylko po to, aby być zgodnym z powiązaną straszną częścią standardu SQL. Jeśli nie zależy ci na kompatybilności z wieloma bazami danych, rozważ przechowywanie danych jako tekstu i dodaj ograniczenie do ograniczenia ich długości. Ograniczenia można zmieniać bez tego problemu z blokadą/przepisaniem tabeli i mogą one wykonywać więcej kontroli integralności niż tylko sprawdzanie słabej długości.

 60
Author: Greg Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-11 21:42:10

W PostgreSQL 9.1 jest łatwiejszy sposób

Http://www.postgresql.org/message-id/[email protected]

CREATE TABLE foog(a varchar(10));

ALTER TABLE foog ALTER COLUMN a TYPE varchar(30);

postgres=# \d foog

 Table "public.foog"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 a      | character varying(30) |
 64
Author: sir_leslie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-01 12:22:20

Ok, pewnie jestem spóźniony na imprezę, ale...

NIE MA POTRZEBY ZMIANY ROZMIARU KOLUMNY W TWOIM PRZYPADKU!

Postgres, w przeciwieństwie do innych baz danych, jest wystarczająco inteligentny, aby używać tylko wystarczająco dużo miejsca, aby zmieścić łańcuch znaków (nawet przy użyciu kompresji dla dłuższych łańcuchów), więc nawet jeśli twoja kolumna jest zadeklarowana jako VARCHAR (255) - jeśli przechowujesz 40-znakowe łańcuchy w kolumnie, użycie spacji będzie wynosić 40 bajtów + 1 bajt narzutu.

Wymóg przechowywania krótkiego ciągu (do 126 bajtów) wynosi 1 bajt plus rzeczywista struna, która zawiera wyściółkę spacji w przypadku charakteru. Dłuższe ciągi mają 4 bajty nad głową zamiast 1. Długie ciągi są kompresowane przez system automatycznie, więc fizyczne wymagania na dysku mogą być mniejsze. Bardzo długie wartości są również przechowywane w tabelach tła, dzięki czemu nie kolidują z szybkim dostęp do krótszej kolumny wartości.

(http://www.postgresql.org/docs/9.0/interactive/datatype-character.html )

Specyfikacja rozmiaru w VARCHAR jest używana tylko do sprawdzania wielkości wstawianych wartości, nie wpływa to na układ dysku. W rzeczywistości, pola VARCHAR i TEXT są przechowywane w ten sam sposób w Postgres.

 42
Author: Sergey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:14

Miałem ten sam problem próbując skrócić VARCHAR z 32 do 8 i uzyskać ERROR: value too long for type character varying(8). Chcę pozostać jak najbliżej SQL, ponieważ używam własnej struktury podobnej do JPA, którą możemy przełączyć na różne DBMS zgodnie z wyborem Klienta(PostgreSQL jest domyślny). Dlatego nie chcę używać sztuczki zmiany tabel systemowych.

Zakończyłem używając USING w ALTER TABLE:

ALTER TABLE "MY_TABLE" ALTER COLUMN "MyColumn" TYPE varchar(8)
USING substr("MyColumn", 1, 8)

Jak zauważył @raylu, ALTER nabywa ekskluzywny Zablokuj stół, aby wszystkie inne operacje były opóźnione, dopóki się nie zakończy.

 22
Author: Matthieu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-22 07:52:19

Oto cache strony opisanej przez Grega Smitha. W przypadku, gdy to również umrze, oświadczenie alter wygląda tak:

UPDATE pg_attribute SET atttypmod = 35+4
WHERE attrelid = 'TABLE1'::regclass
AND attname = 'COL1';

Gdzie twoja tabela to TABLE1, kolumna to COL1 i chcesz ustawić ją na 35 znaków (+4 jest potrzebne do starszych celów zgodnie z linkiem, ewentualnie na górze, o której mowa przez A. H. w komentarzach).

 7
Author: Tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-10 14:41:59

Jeśli umieścisz zmianę w transakcji, tabela nie powinna być zablokowana:

BEGIN;
  ALTER TABLE "public"."mytable" ALTER COLUMN "mycolumn" TYPE varchar(40);
COMMIT;

To działało dla mnie błyskawicznie, kilka sekund na stole z ponad 400k wierszy.

 7
Author: jipipayo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-10 10:13:15

Dodanie nowej kolumny i zastąpienie nowej starą działało dla mnie, na redshift postgresql, zobacz ten link po więcej szczegółów https://gist.github.com/mmasashi/7107430

BEGIN;
LOCK users;
ALTER TABLE users ADD COLUMN name_new varchar(512) DEFAULT NULL;
UPDATE users SET name_new = name;
ALTER TABLE users DROP name;
ALTER TABLE users RENAME name_new TO name;
END;
 4
Author: spats,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-18 03:39:42

Znalazłem bardzo łatwy sposób na zmianę rozmiaru tj. adnotacja @Size (min= 1, max = 50), która jest częścią "Importuj javax./ align = "left" / ograniczenia " tj. "import javax./ align = "left" / ograniczenia.Size; "

@Size(min = 1, max = 50)
private String country;


when executing  this is hibernate you get in pgAdmin III 


CREATE TABLE address
(
.....
  country character varying(50),

.....

)
 1
Author: Tito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-24 09:46:23