/ Forside / Teknologi / Udvikling / SQL / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
SQL
#NavnPoint
pmbruun 1704
niller 962
fehaar 730
Interkril.. 701
ellebye 510
pawel 510
rpje 405
pete 350
gibson 320
10  smorch 260
Flytte data fra en tabel til en anden (MSS~
Fra : Jesper Nielsen


Dato : 21-05-02 21:58

Hejsa NG

Vi skal have flyttet ca. 1.700.000 records fra en tabel til en anden i vores
database.

Er der ikke en metode, hvormed man kan flytte alle records i en tabel (minus
de nyeste 100.000 records) til en anden tabel, eller er jeg tvunget til at
lave en ASP fil, der laver en select statement, og derefter indsætter data i
den nye tabel?

På forhånd tak.

--
Mvh. Jesper



 
 
Jens Gyldenkærne Cla~ (21-05-2002)
Kommentar
Fra : Jens Gyldenkærne Cla~


Dato : 21-05-02 22:13

"Jesper Nielsen" <jn@nielsenit.dk> skrev:

> Er der ikke en metode, hvormed man kan flytte alle records i
> en tabel (minus de nyeste 100.000 records) til en anden tabel,
> eller er jeg tvunget til at lave en ASP fil, der laver en
> select statement, og derefter indsætter data i den nye tabel?

INSERT INTO <tabelnavn> (<felt1>, <felt2>,...)
<SELECT-statement>

Hvis du skal oprette den nye tabel som en (delvis) kopi af den
gamle kan du også bruge:

SELECT <felt1>, <felt2>,... INTO <nytabelnavn>
FROM <gltabel>
WHERE <betingelser>

Når du bagefter skal slette de gamle poster fra den oprindelige
tabel kan du benytte en DELETE-forespørgsel med et JOIN til din nye
tabel:

DELETE FROM <gltabel>
FROM <gltabel> INNER JOIN <nytabel>
ON <gltabel>.<joinfelt> = <nytabel>.<joinfelt>

På den måde kan du sikre at der kun slettes poster der er kopieret
til den nye tabel.

PS: Jeg bruger <xxxx> til at angive objektnavne - klammerne skal
_ikke_ benyttes i den færdige SQL.

--
Jens Gyldenkærne Clausen
MF (Medlem af Fiduso - www.fiduso.dk)

Jesper Nielsen (23-05-2002)
Kommentar
Fra : Jesper Nielsen


Dato : 23-05-02 08:54

> DELETE FROM <gltabel>
> FROM <gltabel> INNER JOIN <nytabel>
> ON <gltabel>.<joinfelt> = <nytabel>.<joinfelt>

Er denne statement korrekt?
Er det meningen, at der skal være 2 gange FROM gltabel? Det ser ikke helt
rigtigt ud fra hvor jeg sidder, men jeg er ikke så stærk udi joins.


> På den måde kan du sikre at der kun slettes poster der er kopieret
> til den nye tabel.

Er det den eneste måde, det kan gøres på?
I ASP ville jeg have lavet en query, der finder lngMaxId = MAX(ID)-100000 og
en DELETE FROM statement, der efter kopieringen slettede alle records der er
mindre end eller lig med lngMaxId.

Kan dette ikke lade sig gøre med en SQL query?
Det vil tage mange resourcer på SQL serveren, hvis den skal gennemgå det
hele for at slette.

--
Mvh. Jesper



Jens Gyldenkærne Cla~ (23-05-2002)
Kommentar
Fra : Jens Gyldenkærne Cla~


Dato : 23-05-02 09:38

"Jesper Nielsen" <jn@nielsenit.dk> skrev:

> Er det meningen, at der skal være 2 gange FROM gltabel?

Ja. Det første angiver hvilken tabel der skal slettes fra (og kan
ikke indeholde et join), mens det andet bruges til at angive
joinbetingelser (det kan undværes hvis man ikke behøver et join).

>> På den måde kan du sikre at der kun slettes poster der er
>> kopieret til den nye tabel.
>
> Er det den eneste måde, det kan gøres på?

Bestemt ikke - der er som regel altid et alternativ.

> I ASP ville jeg have lavet en query, der finder lngMaxId =
> MAX(ID)-100000 og en DELETE FROM statement, der efter
> kopieringen slettede alle records der er mindre end eller lig
> med lngMaxId.

Hvilken tabel finder du lngMaxId fra?
Hvilken tabel sletter du i?
Uden et JOIN eller alternativt en WHERE EXISTS-del kan du ikke være
100 % sikker på at du kun sletter poster der faktisk er kopieret.
Men det er måske også at gå med livrem og seler - en anden måde er
at kontrollere maxID og antal poster i de to tabeller.


> Kan dette ikke lade sig gøre med en SQL query?
> Det vil tage mange resourcer på SQL serveren, hvis den skal
> gennemgå det hele for at slette.

Det tager ikke mange resurser at gennemføre nogle af de INSERTS jeg
har beskrevet. DELETE med JOIN vil muligvis tage ekstratid hvis der
ikke er index på den nye tabel - men hvis id-feltet er det første
er det ikke sikkert at det er noget problem. Ellers kan det løses
ved at lave din kopitabel inden du sætter data ind - så kan du lave
index på id-feltet med det samme.

--
Jens Gyldenkærne Clausen
MF (medlem af FIDUSO - www.fiduso.dk)

Jesper Nielsen (23-05-2002)
Kommentar
Fra : Jesper Nielsen


Dato : 23-05-02 10:28

> > Er det meningen, at der skal være 2 gange FROM gltabel?
>
> Ja. Det første angiver hvilken tabel der skal slettes fra (og kan
> ikke indeholde et join), mens det andet bruges til at angive
> joinbetingelser (det kan undværes hvis man ikke behøver et join).

Okay. Så lærte jeg også noget idag


> > I ASP ville jeg have lavet en query, der finder lngMaxId =
> > MAX(ID)-100000 og en DELETE FROM statement, der efter
> > kopieringen slettede alle records der er mindre end eller lig
> > med lngMaxId.
>
> Hvilken tabel finder du lngMaxId fra?

En tabel, der hedder Dating_ProfileHits. Design:

ID
ul_TargetId
ul_NickName
ul_HitDate
ul_HitDate
Status

Her ville jeg i ASP lave følgende kode:
Set Qry = Conn.Execute("SELECT MAX(ID) AS MID FROM Dating_ProfileHits;")
lngMaxId = CLng(Qry(0)-100000)

Data skal flyttes til tabellen Dating_ProfileHits_Backup med samme design.


> Hvilken tabel sletter du i?

Der skal slettes fra Dating_ProfileHits.
Alle records, der har en ID under lngMaxId (MAX(ID) minus de sidste 100.000
records) skal slettes.


> Uden et JOIN eller alternativt en WHERE EXISTS-del kan du ikke være
> 100 % sikker på at du kun sletter poster der faktisk er kopieret.
> Men det er måske også at gå med livrem og seler - en anden måde er
> at kontrollere maxID og antal poster i de to tabeller.

Det er ikke en vildt kritisk tabel.
Data skal blot flyttes til en ny tabel, fordi det tager LANG tid at udføre
en statement som denne:

SELECT TOP 6 ul_NickName,ul_TargetID FROM Dating_ProfileHits WHERE TargetID
= '" & Session("ul_ProfileID") & "' AND Status = 100 GROUP BY
ul_NickName,ul_TargetID ORDER BY MAX(ID) DESC;

på en tabel med 1,7 millioner records. Og denne statement blev indtil for få
dage siden udført på alle sider på et website med ca. 5 pageviews pr.
sekund. Det kunne tage mange sekunder, med deraf følgende lange svartider og
time outs fra SQL Serveren. Den er midlertidigt fjernet, indtil jeg får
flyttet data til en backup tabel.

Grunden til, at jeg overhovedet vil gemme besøgsdata tilbage fra november
2001 er, at jeg på et tidspunkt vil køre statistik på dataene og lave en
topliste over de mest besøgte profiler m.v..


> Det tager ikke mange resurser at gennemføre nogle af de INSERTS jeg
> har beskrevet. DELETE med JOIN vil muligvis tage ekstratid hvis der
> ikke er index på den nye tabel - men hvis id-feltet er det første
> er det ikke sikkert at det er noget problem. Ellers kan det løses
> ved at lave din kopitabel inden du sætter data ind - så kan du lave
> index på id-feltet med det samme.

Det er såmænd heller ikke INSERT'sene jeg er nervøs for - derimod det, at
den (sådan som jeg ser det - men jeg er som sagt ikke så stærk udi joins)
skal lave et opslag for hver gang den skal slette en record.

--
Mvh. Jesper



Nis Jorgensen (23-05-2002)
Kommentar
Fra : Nis Jorgensen


Dato : 23-05-02 09:54

On Thu, 23 May 2002 09:53:43 +0200, "Jesper Nielsen" <jn@nielsenit.dk>
wrote:

>> DELETE FROM <gltabel>
>> FROM <gltabel> INNER JOIN <nytabel>
>> ON <gltabel>.<joinfelt> = <nytabel>.<joinfelt>
>
>Er denne statement korrekt?
>Er det meningen, at der skal være 2 gange FROM gltabel? Det ser ikke helt
>rigtigt ud fra hvor jeg sidder, men jeg er ikke så stærk udi joins.
>
>
>> På den måde kan du sikre at der kun slettes poster der er kopieret
>> til den nye tabel.
>
>Er det den eneste måde, det kan gøres på?
>I ASP ville jeg have lavet en query, der finder lngMaxId = MAX(ID)-100000 og
>en DELETE FROM statement, der efter kopieringen slettede alle records der er
>mindre end eller lig med lngMaxId.
>
>Kan dette ikke lade sig gøre med en SQL query?

Jo. Een mulighed er at gøre præcis det du siger -

Query 1: Finde lngMaxID i
Query 2: Kopiere alle rækker med ID <= lngMaxID
Query 3: Slette alle rækker med ID <= lngMaxID

en anden er at foretage 1 i en subquery i saavel 2 som 3. Her er det
vigtigt at du holder tungen lige i munden - fx kan der være indsat
rækker i gltabel i mellem 2 og 3 ...

>Det vil tage mange resourcer på SQL serveren, hvis den skal gennemgå det
>hele for at slette.

Jeg tror du overvurderer arbejdsmaengden for serveren. Hvis der ellers
er index paa ID-feltet, tror jeg tidsforskellen paa Jens' query og

DELETE
FROM gltabel
WHERE ID <= lngMaxId

er ubetydelig.
--
Nis Jorgensen
Amsterdam

Please include only relevant quotes, and reply below the quoted text. Thanks

Jesper Nielsen (23-05-2002)
Kommentar
Fra : Jesper Nielsen


Dato : 23-05-02 10:32

> en anden er at foretage 1 i en subquery i saavel 2 som 3. Her er det
> vigtigt at du holder tungen lige i munden - fx kan der være indsat
> rækker i gltabel i mellem 2 og 3 ...

I ASP ville jeg lave følgende statement:
Set Qry = Conn.Execute("SELECT MAX(ID) FROM Dating_Profiles;")
lngMaxId = Qry(0)

lngMaxId ændres således ikke - heller ikke selvom der bliver indsat data
efter den har fundet MAX(ID).


> Jeg tror du overvurderer arbejdsmaengden for serveren. Hvis der ellers
> er index paa ID-feltet, tror jeg tidsforskellen paa Jens' query og

Det kan godt være.
Det er jo selvfølgelig heller ikke noget, der skal udføres hele tiden, men
derimod kun en gang hver 14. dag eller noget i den stil, så jeg holder
antallet af records i Dating_ProfileHits under f.eks. 300.000.

--
Mvh. Jesper



Peter Lykkegaard (24-05-2002)
Kommentar
Fra : Peter Lykkegaard


Dato : 24-05-02 07:02


"Jesper Nielsen" <jn@nielsenit.dk> wrote in message
news:Be1H8.2275$N46.181132@news010.worldonline.dk...
> > DELETE FROM <gltabel>
> > FROM <gltabel> INNER JOIN <nytabel>
> > ON <gltabel>.<joinfelt> = <nytabel>.<joinfelt>
>
> Er denne statement korrekt?
> Er det meningen, at der skal være 2 gange FROM gltabel? Det ser ikke helt
> rigtigt ud fra hvor jeg sidder, men jeg er ikke så stærk udi joins.
>
>
> > På den måde kan du sikre at der kun slettes poster der er kopieret
> > til den nye tabel.
>
> Er det den eneste måde, det kan gøres på?

Du kan evt fyre op under BOL og kikke lidt på

DELETE FROM <gltabel> g
WHERE g.<id> IN (SELECT n.<id> FROM <nytabel> n)

Eller

DELETE FROM <gltabel>
WHERE EXISTS (SELECT <nytabel>.<id> FROM <nytabel> WHERE <gltabel>.<id> =
<nytabel>.<id>)

Efter endt kopiering

Man glemmer ofte disse to muligheder til fordel for joins
Du kan bruge Query Analyzeren til at ekspereimentere lidt ved fx at bruge
selects på de forskellige metoder

mvh/Peter Lykkegaard



Jens Gyldenkærne Cla~ (24-05-2002)
Kommentar
Fra : Jens Gyldenkærne Cla~


Dato : 24-05-02 09:24

"Peter Lykkegaard" <polonline@hotmail.com> skrev:

> DELETE FROM <gltabel> g
> WHERE g.<id> IN (SELECT n.<id> FROM <nytabel> n)

Den er - SVJV - tung rent performancemæssigt.

> Eller
>
> DELETE FROM <gltabel>
> WHERE EXISTS (SELECT <nytabel>.<id> FROM <nytabel> WHERE
> <gltabel>.<id> = <nytabel>.<id>)

Langt bedre - specielt hvis det drejer sig om mange poster.


> Man glemmer ofte disse to muligheder til fordel for joins

Er performance bedre end ved join? Umiddelbart ville jeg mene at
EXIST-modellen skulle give nogenlunde samme performance, mens IN-
modellen ville være langt ringere. Men jeg har ikke praktisk
erfaring med det.

> Du kan bruge Query Analyzeren til at ekspereimentere lidt ved
> fx at bruge selects på de forskellige metoder

Her kan man jo også eksperimentere med at få vist Execution Plans -
for at få en ide om performance.

--
Jens Gyldenkærne Clausen
MF (medlem af FIDUSO - www.fiduso.dk)

Peter Lykkegaard (24-05-2002)
Kommentar
Fra : Peter Lykkegaard


Dato : 24-05-02 09:30


"Jens Gyldenkærne Clausen" <jc@dmf.dk> wrote in message
news:Xns921869BD499B6jcdmfdk@130.225.247.90...
> "Peter Lykkegaard" <polonline@hotmail.com> skrev:
>
> > DELETE FROM <gltabel> g
> > WHERE g.<id> IN (SELECT n.<id> FROM <nytabel> n)
>
> Den er - SVJV - tung rent performancemæssigt.
>
På MSSQL har jeg fundet at den tit er betydeligt bedre end en join, hvis man
skal have et enkelt felt med fra en anden tabel

Men det kræver som sagt lidt eksperimenteren i Query Analyzer for at finde
de vises sten
Btw kræver det samtidig en en fornuftig datamængde at arbejde udfra

mvh/Peter Lykkegaard



Jens Gyldenkærne Cla~ (24-05-2002)
Kommentar
Fra : Jens Gyldenkærne Cla~


Dato : 24-05-02 09:35

"Peter Lykkegaard" <polonline@hotmail.com> skrev:

> På MSSQL har jeg fundet at den tit er betydeligt bedre end en
> join, hvis man skal have et enkelt felt med fra en anden tabel

O.k. Men den bør da stadig ikke kunne hamle op med EXIST? Så vidt
jeg husker min SQL-bibel var det stort set altid bedre at benytte
EXIST end IN ved store datamængder.

Jeg har selv kun mindre databaser (< 10.000 poster), så jeg kan
ikke rigtig teste for det.

--
Jens Gyldenkærne Clausen
MF (medlem af FIDUSO - www.fiduso.dk)

Peter Lykkegaard (24-05-2002)
Kommentar
Fra : Peter Lykkegaard


Dato : 24-05-02 10:44


"Jens Gyldenkærne Clausen" <jc@dmf.dk> wrote in message
news:Xns92186BB7B4E0jcdmfdk@130.225.247.90...
> "Peter Lykkegaard" <polonline@hotmail.com> skrev:
>
> > På MSSQL har jeg fundet at den tit er betydeligt bedre end en
> > join, hvis man skal have et enkelt felt med fra en anden tabel
>
> O.k. Men den bør da stadig ikke kunne hamle op med EXIST? Så vidt
> jeg husker min SQL-bibel var det stort set altid bedre at benytte
> EXIST end IN ved store datamængder.
>
Såvidt jeg ved så kommer det lidt an på konteksten

Anyways - Jeg har prøvet med to tabeller, det viser tydeligt hvor vigtigt et
index egentlig er

A - 26000 poster
B - 58000 poster

--------------------------------------------
foreign key (B) uden index
--------------------------------------------
IN
Duration = 194, CPU = 198, Reads = 144
EXISTS
Duration = 35, CPU = 102, Reads = 144

--------------------------------------------
foreign key (B) alm index
--------------------------------------------
IN
Duration = 199, CPU = 107, Reads = 139
EXISTS
Duration = 219, CPU = 194, Reads = 139

--------------------------------------------
foreign key (B) clustered index
--------------------------------------------
IN
Duration = 199, CPU = 67 Reads = 111
EXISTS
Duration = 219, CPU = 128, Reads = 111

mvh/Peter Lykkegaard



Nis Jorgensen (24-05-2002)
Kommentar
Fra : Nis Jorgensen


Dato : 24-05-02 14:58

On Fri, 24 May 2002 08:01:48 +0200, "Peter Lykkegaard"
<polonline@hotmail.com> wrote:

>
>DELETE FROM <gltabel> g
>WHERE g.<id> IN (SELECT n.<id> FROM <nytabel> n)
>
>Eller
>
>DELETE FROM <gltabel>
>WHERE EXISTS (SELECT <nytabel>.<id> FROM <nytabel> WHERE <gltabel>.<id> =
><nytabel>.<id>)
>
>Efter endt kopiering
>
>Man glemmer ofte disse to muligheder til fordel for joins
>Du kan bruge Query Analyzeren til at ekspereimentere lidt ved fx at bruge
>selects på de forskellige metoder

Efter som de tre queries er _logisk_ ækvivalente, burde en fornuftig
databasemotor lægge samme plan for udførelsen.

--
Nis Jorgensen
Amsterdam

Please include only relevant quotes, and reply below the quoted text. Thanks

Jesper Nielsen (25-05-2002)
Kommentar
Fra : Jesper Nielsen


Dato : 25-05-02 11:35

Mange tak for alle svarene.
Da det ikke er en kommando, der skal udføres konstant og på alle siderne,
men derimod kun en gang om ugen for at holde antallet af records i tabellen
under 500.000, har jeg bestemt mig for at anvende Jens' oprindelige forslag.

--
Mvh. Jesper



Søg
Reklame
Statistik
Spørgsmål : 177559
Tips : 31968
Nyheder : 719565
Indlæg : 6408938
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste