konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

Mam tabelkę:

id klucz przypisanie
1 A 10
2 B 30
3 A
4 B
5 C 10
6 C

Do tabelki dorzucane są rekordy z id, kluczem i pustym przypisaniem. Potrzebuję wykonywanego raz na jakiś czas UPDATE który wszystkim rekordom z pustym "przypisanie" ustawi je, jeśli istnieje już para klucz => przypisanie. Czyli rezultat:

id klucz przypisanie
1 A 10
2 B 30
3 A 10
4 B 30
5 C 10
6 C 10

I jak zrobić najlepiej takie coś? Wydaje mi się że coś w stylu:

UPDATE tabelka SET przypisanie=(SELECT przypisanie FROM tabelka t2 WHERE t2.klucz=tabelka.klucz LIMIT 1) WHERE przypisanie IS NULL

nie jest idealnym rozwiązaniem.Adam T. edytował(a) ten post dnia 21.08.08 o godzinie 18:41
Wojciech Nowak

Wojciech Nowak Konsultant Systemów
Bankowych | Analityk
Systemowy

Temat: Jak najefektywniej zrobić taki UPDATE

Adam T.:
Mam tabelkę:

id klucz przypisanie
1 A 10
2 B 30
3 A
4 B
5 C 10
6 C

Do tabelki dorzucane są rekordy z id, kluczem i pustym przypisaniem. Potrzebuję wykonywanego raz na jakiś czas UPDATE .....

to zależy, czy rekord z kluczem jest zawsze taki sam (tzn. istnieje tylko 1 A 10) czy może być kilka kombinacji.
No i jaki silnik bazy danych. Inaczej da się w Oracle a inaczej w mssql.

pzdr

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

Może być A 10, B 10, C 10. Nie może być A 20, A 30. Baza to mysql.

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

nie znam się na mySQL ale może:

1. indeks na Klucz
2. trigger before insert:

if :new.przypisanie is null then
select przypisanie
into :new.przypisanie
from tabela
where klucz = :new.klucz
and rownum <=1;
end if;

exception
when no_data_found then
raise_application_error( -20100, 'brak poprawnego przypisania');

unikniesz skanowania, ale to zadziała tylko jeśli najpierw pojawia się poprawne przypisanie a dopiero potem te z pustą kolumną przypisanie. tak jak w przykładzie.Dominik Z. edytował(a) ten post dnia 21.08.08 o godzinie 19:48

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

myślałem o triggerze, ale - zależy mi na tym aby insertowanie było jak najszybsze
, no i nie ma gwarancji że będzie takie poprawne przypisanie.

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

a dlaczego update nie jest idealny, chodzi o jego koszt/czas wykonania?
Marcin Lulek

Marcin Lulek Programista -
WebReactor

Temat: Jak najefektywniej zrobić taki UPDATE

hmmm... troche dziwnie mi wyglada ten use case. moze to sie da napisac jakos inaczej, bez takich akrobacji ? z doswiadczenia wiem ze czasem jak czlowiek cos wymysli to ponownie podejscie do tematu skutkuje innym prostszym wydajniejszym rozwiazaniem ;-)

ale ja chyba tez bym myslal o triggerze jesli sie tego nie da przepisac

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

Marcin Lulek:
ale ja chyba tez bym myslal o triggerze jesli sie tego nie da przepisac

Tak ... bo to najprostsze i najmniej kłopotliwe. Ale jednocześnie najbardziej obciążające bazę.

Może przed operacją przepisać potrzebne wartości do innej tabeli i stamtąd je potem zaciągnąć.
Wojciech Nowak

Wojciech Nowak Konsultant Systemów
Bankowych | Analityk
Systemowy

Temat: Jak najefektywniej zrobić taki UPDATE

Adam T.:
Może być A 10, B 10, C 10. Nie może być A 20, A 30. Baza to mysql.

skoro mogą być tylko określone kody to stworzyłbym tablicę z tymi kodami i złączył w updacie dwie tablice zamiast zagnieżdżać selecta w instrukcji update.

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

Wojciech Nowak:

<ciach>
skoro mogą być tylko określone kody to stworzyłbym tablicę z tymi kodami i złączył w updacie dwie tablice zamiast zagnieżdżać selecta w instrukcji update.

Tylko wtedy pozostanie kwestia aktualności danych w tablicy-słowniku z kodami. I dochodzimy z powrotem do triggera.

Chyba że jest inny sposób...
Wojciech Nowak

Wojciech Nowak Konsultant Systemów
Bankowych | Analityk
Systemowy

Temat: Jak najefektywniej zrobić taki UPDATE

Paweł K.:
Tylko wtedy pozostanie kwestia aktualności danych w tablicy-słowniku z kodami. I dochodzimy z powrotem do triggera.

Chyba że jest inny sposób...


tak, tylko jak zmienią się kody to w tablicy głównej zrobi się bałagan (będą stare i nowe ) i select z kluczem zacznie zwracać więcej niż jeden rekord a trigger zgłupieje i zgłosi exception.
Prościej zmienić wartości w tabeli niż przekodowywać.

pzdrWojciech Nowak edytował(a) ten post dnia 21.08.08 o godzinie 20:47
Marcin Lulek

Marcin Lulek Programista -
WebReactor

Temat: Jak najefektywniej zrobić taki UPDATE

Wojciech Nowak:
Paweł K.:
Tylko wtedy pozostanie kwestia aktualności danych w tablicy-słowniku z kodami. I dochodzimy z powrotem do triggera.

Chyba że jest inny sposób...


tak, tylko jak zmienią się kody to w tablicy głównej zrobi się bałagan (będą stare i nowe ) i select z kluczem zacznie zwracać więcej niż jeden rekord a trigger zgłupieje i zgłosi exception.
Prościej zmienić wartości w tabeli niż przekodowywać.

pzdrWojciech Nowak edytował(a) ten post dnia 21.08.08 o godzinie 20:47

a mozesz napisac cos wiecej o tej tabeli ? moze to sie da zaimplementowac zupelnie inaczej a dzialanie bedzie takie samo ?

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

UPDATE tabelka SET przypisanie=(SELECT przypisanie FROM tabelka t2 WHERE t2.klucz=tabelka.klucz LIMIT 1) WHERE przypisanie IS NULL

nie jest idealnym rozwiązaniem.

Właśnie się zorientowałem, że w ogóle to rozwiązanie nie zadziała w MySQL...

http://en.wikibooks.org/wiki/MySQL/Language

>It is currently not possible to update a table while performing a >subquery on the same table. For example, if I want to reset a >password I forgot in SPIP:

>mysql> UPDATE spip_auteurs SET pass =
(SELECT pass FROM spip_auteurs WHERE login='paul') where >login='admin';
>ERROR 1093 (HY000): You can't specify target table 'spip_auteurs' >for update in FROM clause

MySQL mi się zachciało, było przy Postgre zostać :P.

Trigger odpada. Gddybym chciał tak zrobić, to mógłbym też wstawić subquery w insercie, ale insert ma być maksymalnie szybki.

Kody nie są bardzo określone. Po prostu rekordy za pierwszym razem dostają przypisanie "z palca" i chodzi o to, aby potem móc dla takich samych wartości przypisać to samo.

Czyli pozostaje opcja z drugą tabelką. Tylko tymczasową jakąś, czy stałą...
Wojciech Nowak

Wojciech Nowak Konsultant Systemów
Bankowych | Analityk
Systemowy

Temat: Jak najefektywniej zrobić taki UPDATE

Adam T.:

Czyli pozostaje opcja z drugą tabelką. Tylko tymczasową jakąś, czy stałą...

ja bym zrobil tak (mając tablicę główną TABELKA):

1. stworzył tablicę słownik, np. S_TABELKA (id,klucz,przypisanie)

2. insert into S_TABELKA
select distinct * from TABELKA

3.
UPDATE TABELKA
SET przypisanie=s.przypisanie
FROM TABELKA t , S_TABELKA s
WHERE t.klucz=s.klucz and t.przypisanie is null;

(pisze z pamięci więc nie wiem czy sładniowo będzie poprawnie, ale napewno coś w tym stylu działa)
wn
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: Jak najefektywniej zrobić taki UPDATE

Adam T.:
I jak zrobić najlepiej takie coś?

Nie robić w ogóle. Czyli np. jeżeli masz tabelkę (id, klucz, przypisanie, bla bla) to zmieniasz to na
tabelka (id, klucz, bla bla)
przypisania (klucz, przypisanie)
Pozbywasz się redundancji, pozbywasz się decydowania kiedy uaktualnić, dane są relacyjne i w ogóle jest fajnie :-) Uprzedzając dyskusje o niepotrzebnym join'ie - nie widzę nic w nim złego, po to są bazy danych, żeby joinować, grupować, filtrować...

Grzegorz.

PS. Jeżeli jesteś purystą to pewnie na miejscu by było
tabelka (id, id_klucza, bla bla)
przypisania (id_klucza, klucz, przypisanie)
Ciężko powiedzieć czym jest rzeczony klucz - dlatego może lepiej go uajdikowić :-)

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

Wojciech Nowak:
Adam T.:

Czyli pozostaje opcja z drugą tabelką. Tylko tymczasową jakąś, czy stałą...

ja bym zrobil tak (mając tablicę główną TABELKA):

1. stworzył tablicę słownik, np. S_TABELKA (id,klucz,przypisanie)

2. insert into S_TABELKA
select distinct * from TABELKA

3.
UPDATE TABELKA
SET przypisanie=s.przypisanie
FROM TABELKA t , S_TABELKA s
WHERE t.klucz=s.klucz and t.przypisanie is null;

(pisze z pamięci więc nie wiem czy sładniowo będzie poprawnie, ale napewno coś w tym stylu działa)
wn

Dzięki wszystkim za zainteresowanie. Ostatecznie zdecydowałem się na zapytanie w tym stylu. Załatwić sprawę można na kilka sposobów, pocieszam się jednak, że nie istnieje ten jeden oczywisty i idealny, którego ja nie znałem :).

Co do tej propozycji:
Grzegorz G.:
Adam T.:
I jak zrobić najlepiej takie coś?

Nie robić w ogóle. Czyli np. jeżeli masz tabelkę (id, klucz, przypisanie, bla bla) to zmieniasz to na
tabelka (id, klucz, bla bla)
przypisania (klucz, przypisanie)
Pozbywasz się redundancji, pozbywasz się decydowania kiedy uaktualnić, dane są relacyjne i w ogóle jest fajnie :-) Uprzedzając dyskusje o niepotrzebnym join'ie - nie widzę nic w nim złego, po to są bazy danych, żeby joinować, grupować, filtrować...

Grzegorz.

PS. Jeżeli jesteś purystą to pewnie na miejscu by było
tabelka (id, id_klucza, bla bla)
przypisania (id_klucza, klucz, przypisanie)
Ciężko powiedzieć czym jest rzeczony klucz - dlatego może lepiej go uajdikowić :-)

Niby tak, ale tutaj cały ciężar przerzucasz na insertowanie,a to jest właśnie to czego chcę uniknąć, gdyż to insert ma być akurat najszybszy - stąd decyzja o podziale na prościutki insert a co jakiś czas (wykonywany przy innej okazji) update, który zaaktualizuje brakujące dane.
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: Jak najefektywniej zrobić taki UPDATE

Adam T.:
Niby tak, ale tutaj cały ciężar przerzucasz na insertowanie,a to jest właśnie to czego chcę uniknąć, gdyż to insert ma być akurat najszybszy - stąd decyzja o podziale na prościutki insert a co jakiś czas (wykonywany przy innej okazji) update, który zaaktualizuje brakujące dane.

Nie widzę tego ciężaru. Tabelka ,,tabelka'' ma tyle wierszy ile miała. Tabelka ,,przypisania'' ma tyle wierszy, ile jest kodów. Wstawiając do tabelki, nie musisz wstawiać do przypisań. Jeżeli chcesz wstawić oba - wstawiasz oba. Tylko nie mów, że dwa inserty to za duży koszt ;-)

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

Co 2 inserty to nie jeden... kod jest kilkudziesięcioznakowym stringiem, chociaż ukryty, to występuje tutaj skan po indeksie na nim (INSERT OR IGNORE)...

Pomysł ciekawy, ale obciąża to czego ani trochę nie chcę obciążać, a i ten dodatkowy join utrudni życie (wolę raz przemielić update, niż za każdym insertem i selectem dokładać roboty). Ale zapamiętam, w innej sytuacji byłałby to najlepsza opcja.

konto usunięte

Temat: Jak najefektywniej zrobić taki UPDATE

Grzegorz G.:

<ciach>
Nie widzę tego ciężaru. Tabelka ,,tabelka'' ma tyle wierszy ile miała. Tabelka ,,przypisania'' ma tyle wierszy, ile jest kodów. Wstawiając do tabelki, nie musisz wstawiać do przypisań. Jeżeli chcesz wstawić oba - wstawiasz oba. Tylko nie mów, że dwa inserty to za duży koszt ;-)

Koszt faktycznie nieduży, ale zawsze koszt ;-)

Zależy gdzie to będzie używane i jaka aktualność danych jest wymagana. Skoro to nie system produkcyjny (bo Adam napisał, że może być update wartości co jakiś czas), to IMO nie ma co się przejmować tymi kosztami tak bardzo.

[edit mode]powyższy post dużo zmienia, jak pisałem swój, to go nie było jeszcze ;-) [/edit mode]Paweł K. edytował(a) ten post dnia 21.08.08 o godzinie 22:48
Grzegorz G.

Grzegorz G. ASE / Systems
Architect, Syniverse

Temat: Jak najefektywniej zrobić taki UPDATE

Na początek - wiem, że to Ty tu jesteś szefem i to Ty podejmiesz decyzję. Ale...

1. INSERT OR IGNORE - zakładam, że to odpowiednik Ignore dup vals on unique index. Moim zdaniem powinno się zabronić używania tego, tak jak i triggerów oraz WHEN OTHERS THEN w Oracle. Tak czy siak jeżeli jest to Twoim problemem z wydajnością, to trzeba coś z tym zrobić. Jeżeli nie, to pomnożenie go przez dwa (zakłądając, że i na przypisaniach taki potrzeba...w co wątpię) nie zabije.
2. nie chcesz obciążać inserta - zmierzyłeś ile trwa insert? Ile ich masz na sekundę - 1? 10? 100? Zawsze po jednym wierszu czy po więcej?
3. Dodatkowy join utrudni życie - a to stwórz sobie widok który będzie projekcją tego joina. Tobie miło będzie kodować, a mimo beznadziejności mySQL-a nie powinno go to zaboleć (bo przecież klucze będą zindeksowane).
4-te primo, ultimo ;-). Spójność danych - to jest coś, na utratę czego się dobrowolnie zgadzasz. Ryzykowna zagrywka, i szczerze wątpię czy korzyści są warte tego. Ja to wolę mieć lekko powolny, ale poprawny system, niż świetnie szybki, ale czasem się mylący. Bo taki będzie Twój - pomiędzy insertem po update'cie a kolejnym update'm będzie pokazywał niepoprawne dane. Nie, nie poszedłbym taką drogą za nic. Przynajmniej dopóki nie zrozumiem, że jeden insert (ułamek sekundy) jest tak krytyczny w Twoim systemie - a wątpię, żeby taki był skoro zdecydowałeś się na MySQL.

Z najlepszymi intencjami,
Grzegorz.



Wyślij zaproszenie do