![]() |
Brisanje većeg broja slogova iz MySQL baze
Recimo da imam tabelu i da korisnik može da vrši neke prilično složene (i skupe) pretrage nad tom tabelom, a ako mu padne napamet i da izbriše sve rezultate neke od tih pretraga.
U prvom prototipu, jednostavno pamtim id-ove svih slogova koji su pronađeni pretragom i onda ako korisnik tako odluči u jednoj petlji brišem slogove po id-u. Ovo naravno radi, ali gledam da to uradim malo efikasnije/elegantnije. Koliko kapiram, MySQL podržava IN sintaksu, pa bih mogao nešto kao: DELETE FROM tabela WHERE id IN (1, 5, 8...) Koliko vidim, jedino ograničenje za IN je max_allowed_packet, ali ne znam kako bi ovo uticalo na performanse. Da li bi "prepared statement" možda bilo bolje rešenje? Mišljenja, ideje? Hvala unapred. |
Koliko znam ne postoji brži način, osim ako ne brišeš celu tabelu (tada je AFAIK TRUNCATE brži).
Mislim da te max_allowed_packet promenljiva (podrazumevano je 16MB) ne treba da brine, osim ako nemaš nekoliko miliona id-ova u IN klauzuli. |
koliko ja znam IN koristi indexe... koristim ga vrlo cesto upravo za te "delete all checked" operacije i nisam nikad imao nekih problema, niti problema sa perfomansama...cak mislim da je to brze od petlje koja brise jedan po jedan rekord cak i kad je sql izraz prepared (sto do nedavno nije moglo iz php-a, pa sam zato i navikao na IN), jer se ipak sve odvija interno u mysql-u...
u svakom slucaju sa indexiranom tabelom IN radi vrlo lepo.. |
A dodatna tabela (idpretrage, id) ti ne odgovara?
|
@Petar, ivanhoe:
Hvala, to mi savetuje i DBA. Citat:
Interesantan pristup, samo je problem što obično ima mnogo pretraga a malo brisanja. Dokle da držim te pretrage u bazi i kad da ih brišem? Mislim da temp tabela ne dolazi u obzir jer korisnik vrši pretragu tokom jedne (http) konekcije a briše u drugoj. |
Citat:
Što se brisanja tiče, sve zavisi od prirode aplikacije, količine podataka, učestalosti brisanja i punjenja itd. Jedno od rešenja je da se koristi timestamp i da se brišu sve pretrage starije od nekog određenog intervala. |
Kao što rekoh u mom slučaju ima mnogo više pretraga nego brisanja, pa se bojim da tako nešto ne bi bilo uputno, ali generalno gledano nije loša ideja.
Thx. |
Mislim da je ovo prvo resenje optimalnije po nacinu upotreba indexa od ovog sa subquerijem. Koliko se secam literature (nisam preterano koristio subquerije u praksi), do MySQL-a 5.1 optimizacija je bolje funkcionisala kada se ne koriste podupiti.
Ukratko: Kôd:
delete from foo where id in (1,2,3) Kôd:
delete from foo where id in (select id from temp_table) Koga ne mrzi moze i da proba sa malo vecim brojem recorda i odgovarajucim explainom :) |
^Jeste, ali šalješ mnogo više podatka preko "žice" do baze ako je IN lista duga.. Petlja je najlošije rešenje, jer za svaki ID moraš ponovo da se konektuješ na bazu - connection pooling u takvom slučaju je verovatno obavezan, ako su performanse bitne.
Jedno od rešenja jeste da koristiš upit: DELETE FROM t1 WHERE ID IN ( .. originalni upit [izmenjen da selektuje samo ID].. ). Čime si izbegao da šalješ gomilu ID-ova u IN klauzi, ne treba ni pomoćna tabela, itd. Ovako može jer nema potrebe da navodiš "novu" listu ID-ova u IN klauzi, pošto, čini mi se, reče da brišeš sve zapise koji su prethodno bili vraćeni nekim upitom - samo ponovi taj isti, malo izmenjen, SELECT u podupitu za IN. Ako još možeš da taj upit izraziš sa prepared statement-om, ne izgleda mi loše rešenje, posebno što bi baza kod brisanja već mogla da ima keširane potrebne ID-ove nakon prvog upita. Treba probati :) |
mozda neka pametnija baza, mysql ce taj originalni upit da ponovi jer query nije identican (mora do poslednjeg karaktera da bude isti da bi mysql koristio cache)
|
Vreme je GMT +2. Trenutno vreme je 12:28. |
Powered by vBulletin® Verzija 3.6.8
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Copyright © DevProTalk. All Rights Reserved.