Avatar billede cyberesben Nybegynder
22. april 2009 - 04:07 Der er 4 kommentarer og
1 løsning

Udtræk hvor bestemt felt har en unik værdi (undgå dubletter) - hvordan? Group by er for langsom?!

Jeg har en tabel med data over nogle spisesteder, og deres koordinater. De væsentlige felter er nævnt nedenfor:

CREATE TABLE  `r3s`.`provider_foodstuff` (
  `foodstuff_id` int(10) unsigned NOT NULL,
  `name` varchar(100) NOT NULL,
  `lat` float(10,8) NOT NULL,
  `lon` float(10,8) NOT NULL,
  PRIMARY KEY  (`foodstuff_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Mit problem er, at de data som jeg har importeret, indeholder mange dubletter, dvs. der er registreret flere spisesteder på samme adresse og dermed på samme koordinater. Når jeg laver et udtræk vil jeg derfor gerne undgå at disse optræder mere end én gang.

Udtrækket giver oprindeligt 191 rækker inkl dubletter.

Jeg har forsøgt med en
SELECT distinct concat(lat,'/',lon) FROM provider_foodstuff p  WHERE lon>12.4495 AND lon<=12.4995 AND lat>55.7478 AND lat<=55.7978

Som giver mig en liste med 126 unikke koordinatsæt. Men så snart jeg beder om et ekstra felt (id, navn etc), går det galt og jeg får igen den fulde liste på 191, da distinct åbenbart ser på hele kombinationen af valgte felter:

SELECT distinct concat(lat,'/',lon), foodstuff_id FROM provider_foodstuff p,provider_foodstuff_fields f WHERE p.fieldcode=f.foodstuff_field_id AND lon>12.4495 AND lon<=12.4995 AND lat>55.7478 AND lat<=55.7978 AND active=1

Så prøvede jeg med group by:


SELECT * FROM provider_foodstuff p,provider_foodstuff_fields f WHERE p.fieldcode=f.foodstuff_field_id AND lon>12.4495 AND lon<=12.4995 AND lat>55.7478 AND lat<=55.7978 AND active=1 group by concat(lat,'/',lon)

Nu får jeg de ventede 126 linjer, og dubletter er sorteret væk, men udtrækket, som det står her, tog ove 30 sekunder at køre!
Til sammenligning tager det måske 2 ms at køre det uden group by.

HVAD er der galt? Og hvordan opnår jeg det ønskede, uden at det tager ½ minut at udtrække 126 af 191 rækker?

På forhånd tak for hjælpen.

PS: Serveren kører
mysql  Ver 14.12 Distrib 5.0.32, for pc-linux-gnu (i486) using readline 5.2
Avatar billede arne_v Ekspert
22. april 2009 - 04:14 #1
Sæt nogle indexes på de felter som du tester på og grupperer efter.

Og sikre dig at MySQL har nok memory.
Avatar billede cyberesben Nybegynder
23. april 2009 - 22:53 #2
tak, arne_v

Jeg det hjælper gevaldigt på performancen at sætte indexes på - jeg havde nu ikke troet at det var indexes der skulle til, jeg mener bare, hvor svært kan det være for den at lade være med at returnere rækker hvor lat og lon er identiske med nogle tidligere?

Når vi nu snakker om måske 50-100 rækker der returneres, er det jo ikke noget der burde tage en server 30 sek at regne ud
Avatar billede arne_v Ekspert
23. april 2009 - 22:58 #3
Hvis den skal på disk mange gange så tager det tid.
Avatar billede cyberesben Nybegynder
23. april 2009 - 23:02 #4
jeg kan se øverst at det var 191 vs 126 rækker

Hvordan kan det være så svært for den, at når dne har de 191 rækker klar, checker den lige inden de returneres, om en række med samme koordinater er returneret allerede? Og skipper så nogle så der kun returneres 126... Det burde ikke kræve nogen diskaktivitet- databasen fylder måske 2 MB i alt

anyway, læg et svar:)
Avatar billede arne_v Ekspert
23. april 2009 - 23:13 #5
Optimizeren har ikke gennemskuet det som du har gennemskuet. Måske vurderer den ikke antal rækker inden den beslutter sig for hvordan den vil håndtere den query.

Og svar.
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

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