ďťż
 
[Firebird] Odbudowanie kluczy obcych z korekta integralnosci danych ďťż
 
[Firebird] Odbudowanie kluczy obcych z korekta integralnosci danych
Zobacz wiadomości
 
Cytat
A gdyby tak się wedrzeć na umysłów górę, / Gdyby stanąć na ludzkich myśli piramidzie, / I przebić czołem przesądów chmurę, / I być najwyższą myślą wcieloną. . . Juliusz Słowacki, Kordian
Indeks BCB i MySQL subiekt gt fototapeta
 
  Witamy

[Firebird] Odbudowanie kluczy obcych z korekta integralnosci danych



Mariusz - 06-10-2007 00:01
[Firebird] Odbudowanie kluczy obcych z korekta integralnosci danych
  Witam,
Baza danych oparta na Firebird 2.0.
Na pewnym etapie pracy systemu zaszła konieczność usunięcia z bazy danych
WSZYSTKICH zdefiniowanych kluczy obcych a integralność danych została
przerzucona na aplikację.
Oczywiście jak to bywa z aplikacjami po pewnym czasie niektóre dane się
"rozjechały" tzn przy usunięciu z jakiejś tabeli rekordy w powiązanych
tabelach nie zostały wy-null-owane ewentualnie usunięte.
Przyjąłem następujący schemat porządkowania:
1. Utworzenie tabel na backup danych usuwanych/null-owanych danych wedlug
wzorca "backup_NazwaTabeli" z dodatkowa kolumna NumerFK
2. Do tabel backup przerzucilem dane zapytaniem:
insert into backup_NazwaTabeli(lista_pol, NumerFK)
select lista_pol, NumerFK
from NazwaTabeli A left outer join TabelaPowiazana B on
(A.PolePowiazania=B.PolePowiazania)
where B.PolePowiazania is null
Bez wnikania w szczegoly takie zapytanie jest chyba najszybsze. Bylo tez
warunkiem not in (select PolePowiazania from TabelaPowiazana) ale było to
koszmarnie wolne.
3. TU MÓJ PROBLEM - musze z-update-owac tą tabelę NazwaTabeli aby w tych
polach gdzie jest jakaś wartość inna niż istniejąca w TabeliPowiazana
ustawić na null
Niestety w firebirdzie nie mozna (chyba?) w UPDATE uzywac wiecej niz jednej
tabeli do skonstruowania instrukcji upadatujacej tylko dla kazdego rekordu
wykonuje sie podzapytanie więc musiałem niestety zrobić:
update NazwaTabeli
set PolePowiazania=null
where PolePowiazania not in (select PolePowiazania from TabelaPowiazana)
Niestety takie rozwiazanie przy NazwaTabeli i TabelaPowiazana liczacych
sobie po klikadziesiat tysiecy rekordow wykonuje się koszmarnie wolno
(przerwalem po 4 godzinach)
(sprzet: Athlon64/4GB RAM/FB2.0 skompilowany dla 64 bit)

Może macie jakieś inne pomysły jak skonstruowac update-a tak aby wykonywal
sie tak szybko jak ten select insertujący z punktu 2?

Pozdrawiam
Mariusz





Szymon - 06-10-2007 00:01

  Mariusz pisze:
> Witam,
> Baza danych oparta na Firebird 2.0.
> Na pewnym etapie pracy systemu zaszła konieczność usunięcia z bazy danych
> WSZYSTKICH zdefiniowanych kluczy obcych a integralność danych została
> przerzucona na aplikację.

wręcz zajebiste podejście, gratuluję. Pewnie jeszcze transakcje
wywaliliście, bo też przeszkadzały?

> Oczywiście jak to bywa z aplikacjami po pewnym czasie niektóre dane się
> "rozjechały" tzn przy usunięciu z jakiejś tabeli rekordy w powiązanych
> tabelach nie zostały wy-null-owane ewentualnie usunięte.

no właśnie

> Przyjąłem następujący schemat porządkowania:
> 1. Utworzenie tabel na backup danych usuwanych/null-owanych danych wedlug
> wzorca "backup_NazwaTabeli" z dodatkowa kolumna NumerFK
> 2. Do tabel backup przerzucilem dane zapytaniem:
> insert into backup_NazwaTabeli(lista_pol, NumerFK)
> select lista_pol, NumerFK
> from NazwaTabeli A left outer join TabelaPowiazana B on
> (A.PolePowiazania=B.PolePowiazania)
> where B.PolePowiazania is null
> Bez wnikania w szczegoly takie zapytanie jest chyba najszybsze. Bylo tez
> warunkiem not in (select PolePowiazania from TabelaPowiazana) ale było to
> koszmarnie wolne.
> 3. TU MÓJ PROBLEM - musze z-update-owac tą tabelę NazwaTabeli aby w tych
> polach gdzie jest jakaś wartość inna niż istniejąca w TabeliPowiazana
> ustawić na null
> Niestety w firebirdzie nie mozna (chyba?) w UPDATE uzywac wiecej niz jednej
> tabeli do skonstruowania instrukcji upadatujacej tylko dla kazdego rekordu
> wykonuje sie podzapytanie więc musiałem niestety zrobić:
> update NazwaTabeli
> set PolePowiazania=null
> where PolePowiazania not in (select PolePowiazania from TabelaPowiazana)
> Niestety takie rozwiazanie przy NazwaTabeli i TabelaPowiazana liczacych
> sobie po klikadziesiat tysiecy rekordow wykonuje się koszmarnie wolno
> (przerwalem po 4 godzinach)
> (sprzet: Athlon64/4GB RAM/FB2.0 skompilowany dla 64 bit)
>
> Może macie jakieś inne pomysły jak skonstruowac update-a tak aby wykonywal
> sie tak szybko jak ten select insertujący z punktu 2?
>

wrzuć te klucze obce i niech baza to robi, takie obejścia zawsze kończą
się bazą w której dane nadają się tylko do skasowania.




Mariusz - 06-10-2007 00:01

  Użytkownik "Szymon" <alpha@skynet.org.pl_WITHOUT> napisał w wiadomości
news:fe548p$38e$1@inews.gazeta.pl...
> wręcz zajebiste podejście, gratuluję. Pewnie jeszcze transakcje
> wywaliliście, bo też przeszkadzały?

Transakcje zostaly ;)
Chetnie bym jaja urwał osobie która to zrobiła ale już jej nie pracuje nad
tym systemem a ja pierwsze co pomyślałem to odtworzyć wszystko do stanu w
jakim zawsze powinno być...

> wrzuć te klucze obce i niech baza to robi, takie obejścia zawsze kończą
> się bazą w której dane nadają się tylko do skasowania.

Niestety wrzucic nie moge do nieuporządkowanej bazy:
violation of FOREIGN KEY constraint "".
violation of FOREIGN KEY constraint "PK_1" on table "TABELA".
Foreign key reference target does not exist.

Dlatego najpierw muszę wy-null-ować wszystkie dane które nie mają
odpowiedników w tabelach powiązanych.

--
Pozdrawiam
Mariusz




=?ISO-8859-2?Q?Pawe=B3_Matejski?= - 06-10-2007 00:01

  Mariusz wrote:
> Witam,
> Baza danych oparta na Firebird 2.0.
> Na pewnym etapie pracy systemu zaszła konieczność usunięcia z bazy danych
> WSZYSTKICH zdefiniowanych kluczy obcych a integralność danych została
> przerzucona na aplikację.
> Oczywiście jak to bywa z aplikacjami po pewnym czasie niektóre dane się
> "rozjechały" tzn przy usunięciu z jakiejś tabeli rekordy w powiązanych
> tabelach nie zostały wy-null-owane ewentualnie usunięte.
> Przyjąłem następujący schemat porządkowania:
> 1. Utworzenie tabel na backup danych usuwanych/null-owanych danych wedlug
> wzorca "backup_NazwaTabeli" z dodatkowa kolumna NumerFK
> 2. Do tabel backup przerzucilem dane zapytaniem:
> insert into backup_NazwaTabeli(lista_pol, NumerFK)
> select lista_pol, NumerFK
> from NazwaTabeli A left outer join TabelaPowiazana B on
> (A.PolePowiazania=B.PolePowiazania)
> where B.PolePowiazania is null
> Bez wnikania w szczegoly takie zapytanie jest chyba najszybsze. Bylo tez
> warunkiem not in (select PolePowiazania from TabelaPowiazana) ale było to
> koszmarnie wolne.
> 3. TU MÓJ PROBLEM - musze z-update-owac tą tabelę NazwaTabeli aby w tych
> polach gdzie jest jakaś wartość inna niż istniejąca w TabeliPowiazana
> ustawić na null
> Niestety w firebirdzie nie mozna (chyba?) w UPDATE uzywac wiecej niz jednej
> tabeli do skonstruowania instrukcji upadatujacej tylko dla kazdego rekordu
> wykonuje sie podzapytanie więc musiałem niestety zrobić:
> update NazwaTabeli
> set PolePowiazania=null
> where PolePowiazania not in (select PolePowiazania from TabelaPowiazana)
> Niestety takie rozwiazanie przy NazwaTabeli i TabelaPowiazana liczacych
> sobie po klikadziesiat tysiecy rekordow wykonuje się koszmarnie wolno
> (przerwalem po 4 godzinach)
> (sprzet: Athlon64/4GB RAM/FB2.0 skompilowany dla 64 bit)

> Może macie jakieś inne pomysły jak skonstruowac update-a tak aby wykonywal
> sie tak szybko jak ten select insertujący z punktu 2?

Select już zrobiłeś, do tego jego wynik zachowałeś, więc z niego skorzystaj.
W podzapytaniu użyj backup_NazwaTabeli. Przecież tam masz tylko te rekordy,
które mają być null'owane, więc i operator zmieni się na in, co powinno być szybsze.
A jeśli ta tabela ma jakiś PK, to lepiej powiązać po PK, bo zakładam, że
masz na nim index (jak nie to załóż).

--
P.M.





Mariusz - 06-10-2007 00:01

  Użytkownik "Paweł Matejski" <madej@spam.madej.pl.eu.org> napisał w
wiadomości news:fe57om$jam$1@inews.gazeta.pl...
> Select już zrobiłeś, do tego jego wynik zachowałeś, więc z niego
> skorzystaj.
> W podzapytaniu użyj backup_NazwaTabeli. Przecież tam masz tylko te
> rekordy,
> które mają być null'owane, więc i operator zmieni się na in, co powinno
> być szybsze.
> A jeśli ta tabela ma jakiś PK, to lepiej powiązać po PK, bo zakładam, że
> masz na nim index (jak nie to załóż).
Tak tez probowalem ale wbrew pozorom wcale to nie przyspieszylo (wrecz
spowolnilo w przypadku tabel gdzie wszystko bylo ok lub tylko kilka rekordow
bylo nieprawidlowych)
Chyba bede musial na podstawie ilosci rekordow w tabeli backup bede musial
podejmowac decyzje czy uzyc zapisu "in" lub "not in"

przebudowane na not in wyglada to mniejwiecej tak:
update NazwaTabeli
set PolePowiazania=null
where PolePowiazania in
(select distinct A.PolePowiazania from backup_NazwaTabeli A where
A.NumerFK=const_NumerFK and A.PolePowiazania is not null)

dla "not in" wygladalo to tak:
update NazwaTabeli
set PolePowiazania=null
where PolePowiazania not in (select PolePowiazania from TabelaPowiazana)

Troche mnie denerwują takie ograniczenia firebirda ale jak sie nie ma co sie
lubi to narzeka się na to co się ma;)

--
Mariusz Rowiński




wloochacz - 06-10-2007 00:01

  >> Select już zrobiłeś, do tego jego wynik zachowałeś, więc z niego
>> skorzystaj.
>> W podzapytaniu użyj backup_NazwaTabeli. Przecież tam masz tylko te
>> rekordy,
>> które mają być null'owane, więc i operator zmieni się na in, co powinno
>> być szybsze.
>> A jeśli ta tabela ma jakiś PK, to lepiej powiązać po PK, bo zakładam, że
>> masz na nim index (jak nie to załóż).
> Tak tez probowalem ale wbrew pozorom wcale to nie przyspieszylo (wrecz
> spowolnilo w przypadku tabel gdzie wszystko bylo ok lub tylko kilka rekordow
> bylo nieprawidlowych)
> Chyba bede musial na podstawie ilosci rekordow w tabeli backup bede musial
> podejmowac decyzje czy uzyc zapisu "in" lub "not in"
Nie używał podzapytań - użyj złączeń, ale tylko w powiązaniu z procedurą
- będzie szybciej.
Skoro tabelka ma tożsamą strukturę i interesują cię tylko dane
spełniające ograniczenia FK, to inner join jest najszybszym rozwiązaniem
- oczywiście trzeba założyć stosowne indeksy; najlepiej jako primary key.

> przebudowane na not in wyglada to mniejwiecej tak:
> update NazwaTabeli
> set PolePowiazania=null
> where PolePowiazania in
> (select distinct A.PolePowiazania from backup_NazwaTabeli A where
> A.NumerFK=const_NumerFK and A.PolePowiazania is not null)
>
> dla "not in" wygladalo to tak:
> update NazwaTabeli
> set PolePowiazania=null
> where PolePowiazania not in (select PolePowiazania from TabelaPowiazana)
Ja bym napisał to każdej tabelki/zestawu tabel procedurę.
Jeśli tego jest więcej (np. kilkaset) napisałbym program importujący lub
generujący stosowne procedury na serwerze.

> Troche mnie denerwują takie ograniczenia firebirda ale jak sie nie ma co sie
> lubi to narzeka się na to co się ma;)
Tupet to ty kolego masz, oj masz... Pisać tu o "ograniczeniach"...
Acha i jeszcze jedno; zatrudnijecie lub zamówcie konsultacje o osoby,
która ma jakieś pojęcie o Firebirdzie. Będzie lepiej i taniej.

--
wloochacz




Mariusz - 06-10-2007 00:01

  Użytkownik "wloochacz" <wl@no.spam> napisał w wiadomości
news:fe5e9j$jp7$1@nemesis.news.tpi.pl...
> Nie używał podzapytań - użyj złączeń, ale tylko w powiązaniu z procedurą -
> będzie szybciej.
> Skoro tabelka ma tożsamą strukturę i interesują cię tylko dane spełniające
> ograniczenia FK, to inner join jest najszybszym rozwiązaniem - oczywiście
> trzeba założyć stosowne indeksy; najlepiej jako primary key.

Właśnie chciałbym użyć złączenia ale nie bardzo wiem jak w update to zrobić.
W innych RDBMS-ach z którymi miałem do czynienia można było w update podać
listę tabel ze złączeniami lub dodatkową klauzulę from... i w where można
było do tego ograniczyć przelatywnie przez wszystkie wiersze tabeli
update-owanej.
Byłbym bardzo wdzięczny za jakiś przykład jak z procedurą to wykonać bo nie
bardzo rozumiem...

> Ja bym napisał to każdej tabelki/zestawu tabel procedurę.
> Jeśli tego jest więcej (np. kilkaset) napisałbym program importujący lub
> generujący stosowne procedury na serwerze.
Oczywiście w taki sposób to rozwiązałem - Zrobiłem kilka procedur:
1. Tworząca tabelę backup_NazwaTabeli po podaniu jako parametr nazwy tabeli
"NazwaTabeli" na podstawie tabel systemowych odczytuje nazwy i typy pol i
execute statementem tworzę kopię.
2. Procedura z parametrami NazwaTabeli, KluczZrodlowy,
NazwaTabeliPowiazanej, KluczZPowiazanej która kopiuje (szybką metodą)
rekordy które nie mają odpowiedników w TabeliPowiazanej.
3. Ta wolna Procedura Updateująca te rekordy
4. Procedura generująca DDL tworzacy FK i wykonująca go (statement).

Na poczatku to wszystko bylo w jednej procedurze ale Firebird niestety jest
na tyle glupi ze nie widzial kroków poprzednich (nie mozna wewnatrz
procedury commita zrobic a np utworzona tabela backup z execute statement
byla niedostepna dla instrukcji insert)

> Tupet to ty kolego masz, oj masz... Pisać tu o "ograniczeniach"...
> Acha i jeszcze jedno; zatrudnijecie lub zamówcie konsultacje o osoby,
> która ma jakieś pojęcie o Firebirdzie. Będzie lepiej i taniej.

Na jedną drobną operację nie potrzeba mi jakichś wielkich konsultacji -
myślałem że w takiej drobnostce grupa mi pomoże;)

Przegryzlem sie przez wiele RDBMS-ow i przyszlo mi teraz pracowac z
Firebirdem więc uważam że jestem upoważniony do wyrażenia swojej opinii;)
Polubiłem Firebirda za jego prostotę i brak zbędnych bajerów ale czasem tych
bajerów mi brakuje;)

--
Pozdrawiam
Mariusz
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • effulla.pev.pl
  • comp
    [MSSQL2000] Problem z =?ISO-8859-2?Q?tabel=B1/indeksem/zapytanie?==?ISO-8859-2?Q?m_czy_b=B3=B1d_w_bazie_danych=2E=2E=2E?= =?iso-8859-2?Q?=5BMySQL=5D_Wy=B6wietlenie_wszystkich_rekordow _zawierajacy?==?iso-8859-2?Q?ch_duplikat_a__moze_inna_struktura_bazy_danych ?= Konwesja znaków w dump'ie bazy danych - ISO -> utf-8 -> ISO -> utf-8 [laik]Jak =?ISO-8859-2?Q?stworzy=E6/zaczac_tworzyc__ma=B3=B1?==?ISO-8859-2?Q?__baz=EA_danych_na_potrzeby_www=3F?= [mysql] przenoszenie danych =?ISO-8859-2?Q?mi=EAdzy_tabelami_?==?ISO-8859-2?Q?w_r=F3=BFnych_bazach?= Ksiazka - "Podstawowy =?ISO-8859-2?Q?wyk=B3ad_z_system=F3w_?==?ISO-8859-2?Q?baz_danych=22?= Zrywanie =?ISO-8859-2?Q?po=B3aczen_z_baza_danych_-_pos?==?ISO-8859-2?Q?tgresql_=3C-=3E_odbc?= Połączenie bazy danych z wykonaniem polaczenia telefonicznego [mssql] insert do tabeli na podstawie danych z innej tabeli [oracle] Baza danych do kursy Introduction to Oracle9i:PL/SQL ? Skąd ją pobrać ?
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • oefg.opx.pl
  • Cytat

    Decede mihi sole - nie zasłaniaj mi słonca.
    Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści
    Hoc fac - tak czyń.
    A tergo - od tyłu; z tyłu.
    I czarne włosy posiwieją. Safona

    Valid HTML 4.01 Transitional

    Free website template provided by freeweblooks.com