Avatar billede pelskee Nybegynder
29. september 2005 - 12:13 Der er 36 kommentarer og
1 løsning

Optimere slet funktion

er der nogen måde kan man optimere denne slet funktion. den sletter dubletter i tabellen - men det tager mere end 1 dag at løbe den igennem. jeg har pt 175.000 records. og når den kører tager den 99% af min processorkraft
Avatar billede terry Ekspert
29. september 2005 - 12:28 #1
which function?
Avatar billede mugs Novice
29. september 2005 - 12:28 #2
Øhh - Kan vi se din slettefunktion?
Avatar billede pelskee Nybegynder
29. september 2005 - 12:33 #3
damn my bad:

DELETE merge.ID
FROM merge
WHERE (merge.ID) NOT IN (SELECT FIRST (merge.ID) FROM  merge GROUP BY EmailAddress1);
Avatar billede terry Ekspert
29. september 2005 - 13:49 #4
dont you risk deleteing those where there is only one in the group?

You should make sure that you have an index on emailadress1
Avatar billede pelskee Nybegynder
29. september 2005 - 13:56 #5
i dont know if i risk deleting those

'an index on emailaddress1' what does that mean
Avatar billede ldanielsen Nybegynder
29. september 2005 - 14:13 #6
Nu bliver det sjovt :o)

Et index er en ekstra registrering af data i en bestemt kolonne, som Access foretager hvis du beder om det. Hvis du f.eks. skal sortere noget alfabetisk, så vil det foregå MEGET hurtigere hvis den kolonne du sorterer efter er indexeret.

Det sjove er hvor meget hurtigere det kommer til at gå. Jer har selv oplevet at eksekveringstiden kun er 5% af den oprindelige, bare fordi jeg lavede ét index. 30 sek i stedet for 10 min.!!

Din forespørgsel er OK, du får kun slettet dubletter. Men du har ingen styr på hvilken af dubletterne der får lov til at overleve.

Grunden til at den altid vil være langsom at køre er at der foretages en ny select for hver eneste post i tabellen. Men det er man nødt til at gøre.
Avatar billede pelskee Nybegynder
29. september 2005 - 14:17 #7
hvordan får jeg sådan et index ... :)
Avatar billede ldanielsen Nybegynder
29. september 2005 - 14:28 #8
Åbn tabellen i Designvisning, marker kolonnen EmailAddress1, og vælg nederst "Indekser denne kolonne" Du er nødt til at sige at dubletter tillades, ellers kan indexet ikke laves.

Senere kan du evt lave et unikt index for at forhindre at der opstår dubletter igen.
Avatar billede pelskee Nybegynder
29. september 2005 - 16:26 #9
i designvisning satte jeg nu property for EmailAddress1 til indexed ' yes (dublicates ok)

burde jeg så bare kunne gøre min delete sql igen ?
Avatar billede pelskee Nybegynder
29. september 2005 - 21:06 #10
ldanielsen - tak du skal have point
Avatar billede ldanielsen Nybegynder
29. september 2005 - 23:25 #11
Når du siger tak efter 4 t og 40 min, var det så den tid det tog at køre deN :o)

Nej, seriøst, hjalp det? Du skal vænne dig til at lave indexer på "vigtige" felter, ellers vil alle dine databaser blive langsomme når der kommer meget data i dem.

Indexér sådan:

Primary key: Alle tabeller skal have en primær nøgle. Idet du angiver en primær nøgle oprettes der et index for de(n) kolonne(r) der indgår. Så opret blot en primær nøgle, så er det ok.

Fremmednøgler: Når du joiner to tabeller, fx. Kunde med Ordre, vil du have en primær nøgle i Kunde (KundeID), og i Ordre vil du foruden Primær nøglen (OrdreID) have et felt med KundeID, der viser hvilken kunde ordren tilhører. Det felt er en fremmednøgle, og det skal indexeres.

Ofte benyttede felter: Hvis du ofte sorterer kunder efter navn, eller ordrer efter dato, aå kan det være en ide at indexere disse felter. Også felter som benyttes i WHERE klausulen (WHERE col1 < noget) kan indexeres. Disse felter kan du vælge at indexere senere, efter behov, for det er ikke en god ide at indexere alt for meget. Det tager plads, og alle INSERT's og UPDATE's bliver langsommere.

Nå, jeg snakker vist for meget ...  :o)
Avatar billede pelskee Nybegynder
29. september 2005 - 23:36 #12
hehe

tusinde tak for hjælpen

... den kører stadig :)
Avatar billede terry Ekspert
30. september 2005 - 11:18 #13
what was the solution?
Avatar billede pelskee Nybegynder
30. september 2005 - 11:23 #14
the query is not done. its been running since yesterday afternoon
Avatar billede pelskee Nybegynder
30. september 2005 - 11:29 #15
i have closed it since it took up - 99% processor

i dont know what to do
Avatar billede pelskee Nybegynder
30. september 2005 - 11:34 #16
den fylder 6mb pakket hvis der er nogen der vil se på den
Avatar billede ldanielsen Nybegynder
30. september 2005 - 11:36 #17
Så var det jo ikke en løsning :(

Jeg har ikke flere ideer, udover at bruge TOP 1 i stedet for FIRST (som jeg ikke rigtig kender), og lægge en ORDER BY på

DELETE FROM merge
WHERE merge.ID NOT IN (SELECT TOP 1 merge.ID FROM merge GROUP BY EmailAddress1 ORDER BY merge.ID)

Men du lærte da lidt om indexer.
Avatar billede ldanielsen Nybegynder
30. september 2005 - 11:37 #18
Databasen er vel ikke i brug af andre mens du kører den, vel?
Avatar billede ldanielsen Nybegynder
30. september 2005 - 11:40 #19
Jeg vil da gerne se den ...
Avatar billede pelskee Nybegynder
30. september 2005 - 11:42 #20
nej databasen ligger lokalt på min pc

jeg prøver at køre den nye delete :)
Avatar billede pelskee Nybegynder
30. september 2005 - 11:42 #21
kan jeg sende eller ? vil du downloade ?
Avatar billede pelskee Nybegynder
30. september 2005 - 11:46 #22
Avatar billede ldanielsen Nybegynder
30. september 2005 - 13:13 #23
Så er den klaret. Med denne her:

Private Sub Kommandoknap0_Click()
   
    DoCmd.Hourglass True
    DoCmd.SetWarnings False
   
   
    Dim Rec, intNumber
    intNumber = 1000
    Set Rec = CurrentDb.OpenRecordset("SELECT TOP " & intNumber & " Max(ID) AS mID, EmailAddress1 FROM merged GROUP BY EmailAddress1 HAVING COUNT(*) > 1")
   
    If Rec.BOF Then
        MsgBox ("Alle dubletter er slettet")
    Else
        Do While Not Rec.EOF
            DoCmd.RunSQL ("DELETE FROM merged WHERE EmailAddress1 = '" & Rec("EmailAddress1") & "' AND ID <> " & Rec("mID"))
            Rec.MoveNext
        Loop
    End If
    Rec.Close
    Set Rec = Nothing
   
    DoCmd.Hourglass False
    DoCmd.SetWarnings True
   
End Sub


Med intNumber bestemmer du hvor lang tid den skal køre, så hvis du kun tager 1000 poster skal den jo køre nogle gange.

Jeg er som sagt færdig her. Som den er nu sletter den ikke poster hvor emailaddress1 er null
Avatar billede ldanielsen Nybegynder
30. september 2005 - 13:18 #24
Hvis den også skal slette hvor Emailaddress1 er NULL skal du bare køre denne først:

UPDATE merged SET EmailAddress1 = '' WHERE EmailAddress1 IS NULL
Avatar billede pelskee Nybegynder
30. september 2005 - 13:20 #25
dvs jeg skal lave en sql query der ser sådan ud:

Private Sub Kommandoknap0_Click()
   
    DoCmd.Hourglass True
    DoCmd.SetWarnings False
   
   
    Dim Rec, intNumber
    intNumber = 1000
    Set Rec = CurrentDb.OpenRecordset("SELECT TOP " & intNumber & " Max(ID) AS mID, EmailAddress1 FROM merged GROUP BY EmailAddress1 HAVING COUNT(*) > 1")
   
    If Rec.BOF Then
        MsgBox ("Alle dubletter er slettet")
    Else
        Do While Not Rec.EOF
            DoCmd.RunSQL ("DELETE FROM merged WHERE EmailAddress1 = '" & Rec("EmailAddress1") & "' AND ID <> " & Rec("mID"))
            Rec.MoveNext
        Loop
    End If
    Rec.Close
    Set Rec = Nothing
   
    DoCmd.Hourglass False
    DoCmd.SetWarnings True
   
End Sub
Avatar billede ldanielsen Nybegynder
30. september 2005 - 13:24 #26
nænæ, ikke en query.

Det er VBA, lav fx. en formular, sæt en knap på den, og under Events/OnClick sætter du denne kode ind.
Avatar billede pelskee Nybegynder
30. september 2005 - 14:10 #27
bør jeg kunne se at der sker noget når jeg klikker på knappen
Avatar billede pelskee Nybegynder
30. september 2005 - 14:22 #28
nu ser den sådan ud, og der kommer timeglas på når jeg klikker på knappen. det tager 1 min - så er den færdig. men jeg kan ikke se der er sket noget i merged tabellen
Avatar billede pelskee Nybegynder
30. september 2005 - 14:22 #29
Private Sub Command1_Click()
   
    DoCmd.Hourglass True
    DoCmd.SetWarnings False
   
   
    Dim Rec, intNumber
    intNumber = 1000
    Set Rec = CurrentDb.OpenRecordset("SELECT TOP " & intNumber & " Max(ID) AS mID, EmailAddress1 FROM merged GROUP BY EmailAddress1 HAVING COUNT(*) > 1")
   
    If Rec.BOF Then
        MsgBox ("Alle dubletter er slettet")
    Else
        Do While Not Rec.EOF
            DoCmd.RunSQL ("DELETE FROM merged WHERE EmailAddress1 = '" & Rec("EmailAddress1") & "' AND ID <> " & Rec("mID"))
            Rec.MoveNext
        Loop
    End If
    Rec.Close
    Set Rec = Nothing
   
    DoCmd.Hourglass False
    DoCmd.SetWarnings True
   
End Sub
Avatar billede ldanielsen Nybegynder
30. september 2005 - 14:38 #30
Hvis du tæller poster i tabellen kan du se at der bliver færre og færre.

Hvis du nu laver intNumber om til 10 og midlertidig fjerner linien DoCmd.SetWarnings False (evt. ved at sætte en ' foran den), så skal du bekræfte hver enkelt sletning. Upraktisk, men så kan du se at der sker noget.

Prøv at sætte den til 10000, og sæt linien DoCmd.SetWarnings False ind igen. Så skulle det være nok at køre den 20 gange. Eller sæt den til 1000000, så klarer den det i én omgang, til gengæld tager det nok en 10 minutters tid.

Så længe der er adresser med EmailAddresse1 NULL vil den aldrig blive "færdig", dvs at den vil aldrig sige "Alle dubletter er slettet
Avatar billede pelskee Nybegynder
30. september 2005 - 15:08 #31
det er fanme vildt. nej hvor kører den hurtigt igennem

er der nogen 'catch' ved det ?
Avatar billede pelskee Nybegynder
30. september 2005 - 15:10 #32
hvordan kan det være den kan køre det så hurtigt når min query har stået i mange mange timer de andre dage ?
Avatar billede pelskee Nybegynder
30. september 2005 - 15:16 #33
kan man lave det med en condition så hvis det er noget i feltet pspt_id så sletter den den record som ikke har noget i det felt. jeg vil nemlig helst beholde alle med pspt_id og så kun slette dem uden hvis der er dubletter.
giver det mening ?
Avatar billede ldanielsen Nybegynder
01. oktober 2005 - 19:29 #34
Ingen catch

Jeg går ud fra at grunden til at det er hurtigere er, at programmet "slipper kontrollen" igen og igen. Når du laver den oprindelige sletteforespørgsel vil access forsøge at sørge for at den oprindelige forespørgsel stadig er opdateret. Det vil sige at hver gang du sletter en post skal den oprindelige forespørgsel foretages igen, for forholdene har jo ændres. Om man kan komme ud over det, det ved jeg ikke.

Prøv at lave denne linie om til:
DoCmd.RunSQL ("DELETE FROM merged WHERE EmailAddress1 = '" & Rec("EmailAddress1") & "' AND ID <> " & Rec("mID") & " AND (pspt_id IS NULL OR pspt_id = ''"))

Så skåner den poster med pspt_id, men til gengæld kan der godt være dubletter stadig.


Hvis pspt_id for en given EmailAddress1 er fast, så kunne du sørge for at udfylde den for alle poster:

UPDATE merged m1 SET m1.pspt_id = (SELECT m2.pspt_id FROM merged m2 WHERE m2.EmailAddress1 = m1.EmailAddress1 AND (pspt_id IS NOT NULL OR pspt_id <> '')) WHERE pspt_id IS NULL OR pspt_id = ''

Denne ville køre i MSSQL. Jeg ved ikke om Access understøtter denne form for subqueries.

Nu vil alle have pspt_id, og funktionen kan køres i sin oprindelige form (uden ovenstående tilføjelse)
Avatar billede pelskee Nybegynder
03. oktober 2005 - 07:29 #35
tusinde tak for hjælpen

du skal have point
Avatar billede ldanielsen Nybegynder
03. oktober 2005 - 09:43 #36
Selv tak.

Jeg fik dem jo allerede for nogle dage siden, men tak for dem.

I øvrigt, en lille typo i mit sidste indlæg:

DoCmd.RunSQL ("DELETE FROM merged WHERE EmailAddress1 = '" & Rec("EmailAddress1") & "' AND ID <> " & Rec("mID") & " AND (pspt_id IS NULL OR pspt_id = '')")
Avatar billede pelskee Nybegynder
03. oktober 2005 - 11:03 #37
;)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Dyk ned i databasernes verden på et af vores praksisnære Access-kurser

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester