29. september 2005 - 12:13Der 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
I dette særtema om aspekter af AI ser vi på skiftet fra sprogmodeller til AI-agenter, og hvordan virksomheder kan navigere i spændet mellem teknologisk hastighed og behovet for menneskelig kontrol.
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.
Å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.
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.
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
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
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
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
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
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 ?
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)
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 = '')")
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.