Vinnaren i pepparkakshustävlingen!
2013-09-18, 15:50
  #1
Medlem
Kod:
SELECT tender.document_number
FROM account_listener
JOIN tender_cpv ON tender_cpv
.cpv_code account_listener.cpv_code
JOIN tender_nuts 
AS tn1 ON account_listener.nuts_2003_code tn1.nuts_code
JOIN tender_nuts 
AS tn2 ON account_listener.nuts_2008_code tn2.nuts_code
JOIN tender ON tender_cpv
.document_number tender.document_number
WHERE account_listener
.account_id '1'
GROUP BY tender.document_number 

Så här ligger det till.
Jag har en tabell som heter tender som innehåller uppgifter om upphandlingar.
Tabellen tender har två saker som är viktiga, ena är cpv_code, de andra är nuts_code. Dessa är sparade i en separat tabell, tender_cpv för cpv_code och tender_nuts för nuts_code.

Sedan kan användaren välja att skapa en bevakning genom att lägga till en cpv_kod samt en nuts_kod som han/hon vill bevaka. Den tabellen heter account_listener.

Tabellen account_listener har kolumnerna cpv_code, nuts_2003_code och nuts_2008_code.

Jag vill få ut alla rader som matchar cpv_code och (nuts_2003_code ELLER nuts_2008_code) från tender.

Hur ska jag skriva min query?

Querying tar över 5 minuter att köra.

Det finns 10 000 records i tender
Det finns 24 000 records i tender_cpv
Det finns 9 000 records i tender_nuts

PS
inte sovit inatt i är heeelt borta i huvudet asså. Är otroligt tacksam om jag får klart detta idag
__________________
Senast redigerad av newone 2013-09-18 kl. 15:57.
Citera
2013-09-18, 16:10
  #2
Medlem
Skrev om querying själv, blev lite bättre tid men är fortfarande helt efterblivet.

Citat:
SELECT * FROM tender
LEFT JOIN tender_cpv ON tender_cpv.document_number = tender.document_number
LEFT JOIN tender_nuts ON tender_nuts.document_number = tender.document_number
JOIN account_listener ON account_listener.cpv_code = tender_cpv.cpv_code AND (account_listener.nuts_2003_code = tender_nuts.nuts_code OR account_listener.nuts_2008_code = tender_nuts.nuts_code)
Citera
2013-09-18, 16:58
  #3
Medlem
fnirps avatar
Citat:
Ursprungligen postat av newone
Hur ska jag skriva min query?

Querying tar över 5 minuter att köra.

Det finns 10 000 records i tender
Det finns 24 000 records i tender_cpv
Det finns 9 000 records i tender_nuts

Hinner tyvärr inte skriva något utförligt svar nu, men fem minuter för så få records verkar galet. Får du till någon cross join? Dvs databasen får jobba med ett 10 000 * 24 000 * 9 000 = 2160 miljarder poster stort recordset värsta fall.

När jag började min databaskarriär, var databasmotorernas egen optimering av sql-koden usel, så då byggde man frågan från den minsta tabellen till den största tabellen om det gick... Dvs i ditt fall tender_nuts joinas med tender som joinas med tender_cpv. Kan vara ett tips på vägen.

Indexering är en annan prestationshöjare. Har du index på de kolumner du joinar med?
Citera
2013-09-18, 17:08
  #4
Medlem
Citat:
Ursprungligen postat av fnirp
Hinner tyvärr inte skriva något utförligt svar nu, men fem minuter för så få records verkar galet. Får du till någon cross join? Dvs databasen får jobba med ett 10 000 * 24 000 * 9 000 = 2160 miljarder poster stort recordset värsta fall.

När jag började min databaskarriär, var databasmotorernas egen optimering av sql-koden usel, så då byggde man frågan från den minsta tabellen till den största tabellen om det gick... Dvs i ditt fall tender_nuts joinas med tender som joinas med tender_cpv. Kan vara ett tips på vägen.

Indexering är en annan prestationshöjare. Har du index på de kolumner du joinar med?

Ja asså jag blir galen, fattar inte hur det kan ta så lång tid.
Jag har index på allt jag använder i mina joins och i where clause.

Så här ser en explain ut av själva queryin:

Kod:
id 	select_type 	table 	type 	possible_keys 	key 	key_len 	ref 	rows 	Extra 	
1 	SIMPLE 	account_listener 	ALL 	cpv_code,nuts_code 	NULL	NULL	NULL	1 	NULL
1 	SIMPLE 	tender_nuts 	index 	NULL	nuts_code 	10 	NULL	9373 	Using where; Using index; Using join buffer (Block Nested Loop)
1 	SIMPLE 	tender 	eq_ref 	PRIMARY 	PRIMARY 	152 	func 	1 	Using where
1 	SIMPLE 	tender_cpv 	index 	NULL	cpv_code 	10 	NULL	26644 	Using where; Using index; Using join buffer (Block Nested Loop)

Har testat att skriva queryin på 100 olika sätt men varje gång jag blandar in tender_nuts så går allting åt helvete. Det är precis som att det är för många joins.

Jag vill helt enkelt ha ut alla tender som matchar personens bevakning genom att joina account_listener mot tender_cpv & tender_nuts och skriva ut resultatet som joinas mot tabellen tender.


PS:
Tog bort indexen eftersom jag bytte namn på någon kolumn (vet inte om det var reindexeringen som hjälpte), ändrade queryin till:

Kod:
SELECT FROM account_listener AL
JOIN tender_nuts TN ON TN
.nuts_code AL.nuts_2003_code
JOIN tender_cpv TC ON TC
.cpv_code AL.cpv_code AND TC.document_number TN.document_number 
JOIN tender T ON T
.document_number TC.document_number 

och helt plötsligt tog det 0.01 sek...
__________________
Senast redigerad av newone 2013-09-18 kl. 17:29.
Citera

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback