06. juli 2006 - 15:26Der er
15 kommentarer og 1 løsning
Alt for mange joins i view
Jeg har følgende query, hvor outputtet er godt nok, men jeg har brug for en lidt mere intelligent måde at gøre det på... Skal bruges til et View
SELECT P.indeks, PD1.val, PD2.val, PD3.val, PD4.val, PD5.val, PD6.val, PD7.val, PD10.val, PD16.val FROM Products P LEFT JOIN ProductData PD4 ON P.indeks = PD4.product AND PD4.dataType = 4 LEFT JOIN ProductData PD7 ON P.indeks = PD7.product AND PD7.dataType = 7 LEFT JOIN ProductData PD6 ON P.indeks = PD6.product AND PD6.dataType = 6 LEFT JOIN ProductData PD10 ON P.indeks = PD10.product AND PD10.dataType = 10 LEFT JOIN ProductData PD16 ON P.indeks = PD16.product AND PD16.dataType = 16 LEFT JOIN ProductData PD1 ON P.indeks = PD1.product AND PD1.dataType = 1 LEFT JOIN ProductData PD5 ON P.indeks = PD5.product AND PD5.dataType = 5 LEFT JOIN ProductData PD3 ON P.indeks = PD3.product AND PD3.dataType = 3 LEFT JOIN ProductData PD2 ON P.indeks = PD2.product AND PD2.dataType = 2
Bemærk at alle PD'erne er fra samme tabel, men jeg skal have dem ud i en enkelt tuple
tja det mente jeg nok også, men det kunne være der var en smart funktion der var gået min næse forbi.
btw SQL 2005
Under design og ca 90% inde i implementation, var det en fornuftig opbygning, indtil kunden ligepludselig fik noget galt i halsen, og kom på andre tanker. SÅ nu står jeg ved at stort performance issue pga alle disse joins.
Men så må du forklare hvorfor det skal være på "langs". En SQL-forespørgsel skal give dig de data du har brug for, mens præsentationen for brugeren klares andetsteds. Hvis du får data ud sådan ca. som skitseret kan du vil programmere dig til at vise det på "langs"
der er ca. 3,5 mill poster i products (vokser med ca. 20K om månedet) der er ca 13,5 mill poster i tabellen (vokser med ca. 90K om månedet) desuden laves der allerede en temlig kompliceret prisberegning pr. produkt, som ligger i en adskilt funktion, der joines med det enkelte produkt. (se nedenstående)
der kommer til at være et throughput på ca. 25-40 forspørsler på 1-10 produkter i sek.
pt. er det processor og IO der giver balladen.
i morgen bliver der smidt en extra proc. i (nr.2/2), og en extra GB ram (bliver til 3 GB) men serveren allerede max'et ud med et RAID1 til OS og et RAID5 med 4 diske til data, som desværre holder både data og logs (Temp database ligger dog på RAID1)
Gode forslag er velkommende (dog er der ikke økonomi til megen udvidelse)
...... Men måske du har et godt forslag til denne...
SELECT P.indeks, P.title, P.article, PP.Price, PP.Discount, PP.shippingFee, PP.savings, PP.PriceIndeks FROM Products P INNER JOIN V_ProductDataView PDV ON P.indeks = PDV.ProductIndeks INNER JOIN dbo.fn_GetProductPrice(P.indeks, @Currency, @Purchaser) PP ON P.indeks = PP.ProductIndeks
Hvor dbo.fn_GetProductPrice() er en inline table function, der returnere 5 kolonner som alle skal bruges i hvert enkelte row af slut produktet.
Problemet med ovenstående er at man ikke kan bruge P.indeks som parameter til funktionen da det vil give følgende fejl "The multi-part identifier "P.indeks" could not be bound." (Ved godt det ikke kan lade sig gøre)
Jeg har også prøvet...
SELECT P.indeks, P.title, P.article, dbo.fn_GetProductPrice(P.indeks, @Currency, @Purchaser) FROM Products P INNER JOIN V_ProductDataView PDV ON P.indeks = PDV.ProductIndeks
Men man kan jo kun kalde en function der returnere scalar værdier som kolonne i en select statement
Måske du kender en funktion der tilføje alle kolonnerne fra en table function til min select statement ?
PT. brugere jeg en Cursor til hente 10 fully loaded produkter, og den kan også mærkes på performance (sidder pt dybt begravet i mine execution plans)
ericjacobsen -> Hvis jeg skal bruge 10 produkter, som alle bliver multipliceret ud på 9 rækker (tilsvarende antallet af datatypes), vil jeg skulle returnerer et recordsæt på 90 poster, som efterfølgende skal sendes over webservices, til en ekstern klient.
Oprindeligt var det tilsigtede at klienten skulle hente 10 produkter, og for hvert produkt hente en collection af ProductData. Dette er desværre blevet udelukket, og det er blevet et krav at hente alle værdier på en enkelt Product record.
Pt. er dette blevet pålagt databasen, men det kan selvfølgelig være det skal ligges over i mit Data Access Layer (C#) i steden for, ved at iterere over et dataset, og fylde min DTO's property gennem reflections Under alle omstændigheder er det udelukket at det skal håndteret på klienten.
Men det er jo også derfor jeg spørger herinde... Så jeg kan få tilsagn fra andre kloge hoveder.
90 poster i sig selv er vel ikke noget problem. Uden at kunne gå i detaljer med din problemstilling skal du vel finde den billigste kombination af sql-kald + DAL-kode + klientkode (hvis der må ændres noget der). Så er det bare et gå i gang ;)
erik -> Det tror du har ret. Er nu gået i gang med at ligge kald til ProductData over i mit DAL.
ldanielsen -> Nu er problemet jo ikke lige frem om det er pænt eller ej. Performance er mit issue, og dit forslag om at kalde en scalar function 9 gang i min select statement vil være en væsentlig forringelse.
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.