Sida 1 av 1

SQL insert med cross join

Postat: 14 februari 2010, 16:10:36
av Gildebrand
Hejsan!
Jag skulle behöva lite hjälp med en SQL-grejja.
Jag behöver lägga till poster i min tabell, resultat, utifrån två andra poster, Students och Subjects.

Med följande fråga kan jag få ut den information som jag vill skicka in i min tabell resultat.

Kod: Markera allt

select NEWID() as ID, Students.ID as Elev_ID, Subjects.ID as Subject_ID
from Students 
cross join Subjects
ID Elev_ID Subject_ID
99FDA544-3D80-4C9D-AEAD-7E5E4CF005FD | 56FA3FB4-7E1E-4478-A47F-0AE76BF5150F | 1
02D34D45-1003-494A-82D7-DEAAD20428BA | EBC77626-A90B-4BFD-BD98-2E0CAB30C711 | 1
774501FB-94F6-46DE-A2A1-6AAF6D9936F3 | 4292D6B2-5123-4BE0-ADA0-83A767CFE3F9 | 1
D7DC3811-7283-43B4-AAA1-E08E1C5B5338 | FDD418A2-4C27-4779-BD9C-EE53904B010F | 1
4C864275-5F96-45F3-AD7D-B1319E791529 | 56FA3FB4-7E1E-4478-A47F-0AE76BF5150F | 2
6AAE15FB-BB89-4FD3-A44D-B1745591B85F | EBC77626-A90B-4BFD-BD98-2E0CAB30C711 | 2
CD7ECC03-01D1-4D04-904B-7025CD63C002 | 4292D6B2-5123-4BE0-ADA0-83A767CFE3F9 | 2
0650ABDE-BA91-4BCE-B4DD-B574D7C29AC3 | FDD418A2-4C27-4779-BD9C-EE53904B010F | 2
Så kan svaret se ut när jag ställer den frågan. Nu vill jag peta in allt det här i tabellen resultat, och skulle behöva lite hjälp med att skriva en SQL-Fråga som sköter allt det hära med cross join och NEWID osv.

Re: SQL insert med cross join

Postat: 14 februari 2010, 16:26:52
av sodjan
Nu så framgår det ju i princip ingenting av vilka miljö du jobbar i
(varför inte ? Är din databasmiljö hemligt på något sätt) men i
princip är det väl bara att göra en INSERT med det där. Något i stil med :

Kod: Markera allt

insert into resultat (ID, Elev_ID, Subject_ID)
  select NEWID() as ID, Students.ID as Elev_ID, Subjects.ID as Subject_ID
    from Students
    cross join Subjects
Eller om tabellen resultat bara ha de tre columnerna :

Kod: Markera allt

insert into resultat
  select NEWID() as ID, Students.ID as Elev_ID, Subjects.ID as Subject_ID
    from Students
    cross join Subjects
Eller lite kortare :

Kod: Markera allt

insert into resultat
  select NEWID(), Students.ID, Subjects.ID
    from Students
    cross join Subjects

Re: SQL insert med cross join

Postat: 14 februari 2010, 16:44:59
av Gildebrand
Sodjan! DU ÄR KUNG!!!!
Jag var inne på det sätt som du gjorde här under ett tag, men måste ha skrivit fel.
Inte hemligt alls. SQL Server 2008. Rullar på en DL380, 8GBram, tror det är två stycken 4kärniga Xeon-proppar. 8st 146GB 10k. I all enkelhet :D

Tror jag krånglade till det för mycket

Re: SQL insert med cross join

Postat: 14 februari 2010, 16:53:16
av sodjan
OK. MS SQL Server (eller i princip Sybase SQL Server).
Då fungerar ofta de gamla Sybase kunskaperna helt OK... :-)
Jag gissade i och för sig på MySQL, men det här är ganska
så standard ANSI SQL så det bör fungerar nästan överallt...

> Tror jag krånglade till det för mycket

Ingen aning, du hemlighöll ju även både det faktum att
du *hade* försökt själv och *hur* du hade försökt... :-)

Re: SQL insert med cross join

Postat: 14 februari 2010, 17:32:04
av Gildebrand
Jag trodde microsoft hade gått ifrån Sybase-kärnan!???

Re: SQL insert med cross join

Postat: 14 februari 2010, 19:13:26
av sodjan
Jag vet inte riktigt vad som har hänt de senaste året, men
för ett tag sedan (tja, säg 10-15 år) så var det väldigt mycket
Sybase-stuk på det hela fortfarande. MS hade lagt till lite
lull-lull i form av lite GUI's. En fungerande databas-motor
är inget som man snyter ur näsan direkt. Men å andra sidan
så var ju aldrig Sybase speciellt bra, så man kan ju ha lite
förståelse för om MS har jobbat lite med den...

Jag kollade lite nu och så vitt jag kan se så stöder MS SQL Server
fortfarande inte "Reapeatable Read" för read-only transaktioner
utan att också blockera read/write transaktioner. D.v.s att om man
vill köra ett antal summeringar ur databasen, och behövera köra om
flera olika SELECT, så är det vanligt att man vill få resultat som är
jämförbara med varandra, d.v.s att det inte händer något (nya eller
ändrade poster) mellan de olika SELECT'en. Samtidigt så vill man ju
inte att detta hindrar andra användare/processer att fortsätta med de
löpande jobbet. Då får man direkt ett gäng arga användare på telefon... :-)

Re: SQL insert med cross join

Postat: 14 februari 2010, 19:20:10
av Gildebrand
Jag måste iallafall säga att jag är mäkta imponerad av prestandan i SQL-server 2008. Min far visade mig mig en tabell med cirkus 40 miljoner poster. Den var såklart indexerad, men ändå. Svar direkt från en tabell med så många poster är imponerande, enligt mig iallafall. Nu kunde han tyvärr inte svara på min lilla fråga som du löse så fint.

Jag läste lite häromdagen om SQL-server genom tiderna, och om jag inte minns fel så stod det att de gick ifrån sybase helt och hållet i och med Server 2005

Re: SQL insert med cross join

Postat: 14 februari 2010, 20:57:00
av sodjan
Om du med "svar direkt" menar svar på en SELECT med unik nyckel (som unikt
pekar ut en enda post) så spelar ju inte tabellstorleken någon speciell roll alls.
Det går i princip lika snabbt oberoende på tabellstorlek. Det ökar med en eller
ett par I/O för varje gång som index djupet öker med ett. I exemplen nedan har
primärindex ett djup på 6 nivåer, det är lite onödigt mycket och skulle lätt
kunna minskas genom att öka page-storleken på indexet (sannolikt bara
satt som default från början).

> Den var såklart indexerad, men ändå.

Det är inte "men ändå". Det är fullkommligt avgörande.

Och vad betyder "svar direkt" igentligen ?
0.1, 0.01 eller 0.001 s ? Alla dessa tider skulle upplevas som "direkt"
om man bara sitter bredvid och tittar, men det är en väldig skillnad i tid!
Svarstider (i alla fall när det gäller korta tider) blir ganska
ointressanta om man inte mäter dom med något verktyg.

Jag körde ett par exempel på en tabell med ca 16,5 milj poster.
Postlängd ca 100 tecken och tar upp ca 1.6 GB utrymme.
Kört på en 666 MHz maskin, 4GB minne. Jag har ersatt de verkliga
tabell och fält namnen med dummynamn...

Kod: Markera allt

SQL> select count(*) from tab1;

    16542308
1 row selected
Först en enkel select med unika nycklar :

Kod: Markera allt

SQL> set timing on;
SQL> select fld1, fld2
cont> from tab1 where fld1 = 'abcdef'
cont> and fld2 = 123456;
 fld1                    fld2
 abcdef                  123456
1 row selected
Timing: Elapsed:    0 00:00:00.05 Cpu:    0 00:00:00.00
SQL>
0.05 s "elapsed" och "CPU" inte mätbart med 10 ms upplösning. Jag fick
köra om samma SELECT ca 10 gånger för att det skulle ticka fram
en hundradels CPU sek. Så säg att varje SELECT tar ca 1 ms CPU-tid.
Så att en databas svarar "direkt" när man söker med unika nycklar
är knappast att imponeras av. Det är naturligtsvis helt förväntat.

Just i detta fall har det använda indexet

Om man däremot kör mot ett fält som inte är indexerat så blir det naturligtsvis helt annolunda :

Kod: Markera allt

SQL> select fld1, fld2
cont> from tab1 where fld3 = 86716;
 fld1                    fld2
 abcdef                  12345
 abcdef                  23456
...
...
 abcdef                  34567
 abcdef                  45678
140 rows selected
Timing: Elapsed:    0 00:03:04.87 Cpu:    0 00:02:43.44
Så här drog det iväg i ca 2 min och 45 sekunder, men nu är det en total
table-scan av hela tabellen med 16.5 milj poster, så det är ju ett helt annat "jobb".
Att inte totaltiden (ca 3 min) skilljer så mycket beror på att databasen "ser" att
man läser tabellen sekvensiellt och slår på "asynkron pre-fetch" automatiskt. Så
posterna läses från disk lite innan de behövs, så att säga. Databasen har hela tiden
koll på att de pre-fetchade posterna faktiskt används, om inte så slår den av
pre-fetchen igen. Det sker dynamiskt hela tiden.

Lite statistik från databasen från den senaste körningen. Först "Record Statistics" taget
mitt under körningen. Databasen har alltså som mest "kollat" på lite drygt 100.000 poster
per sekund, vilket stämmer bra med 16.5 milj / 163 sekunder...

Kod: Markera allt

Node: xxxx (1/1/1)     Oracle Rdb V7.2-401 Perf. Monitor 14-FEB-2010 19:47:02.56
Rate: 1.00 Second              Record Statistics            Elapsed: 00:01:27.96
Page: 1 of 1          device:<yyyy.RDB_3>aaaaaDB.RDB;5          Mode: Online
────────────────────────────────────────────────────────────────────────────────
statistic.........      rate.per.second............. total....... average......
name..............      max..... cur..... avg....... count....... per.trans....
record marked                  0        0        0.0            0           0.0
record fetched            101260    82848    42988.1      3781234           0.3
 fragmented                     0        0        0.0            0           0.0
record stored                  0        0        0.0            0           0.0
 fragmented                     0        0        0.0            0           0.0
pages checked                  0        0        0.0            0           0.0
     saved IO                  0        0        0.0            0           0.0
    discarded                  0        0        0.0            0           0.0
record erased                  0        0        0.0            0           0.0
 fragmented                     0        0        0.0            0           0.0
temp record marked             0        0        0.0            0           0.0
 fetchd                         0        0        0.0            0           0.0
 stored                         0        0        0.0            0           0.0
 erased                         0        0        0.0            0           0.0
sequential scan                1        0        0.0            1           0.0
 record fetched            101260    82848    42988.0      3781233           0.3
Cachen räcker inte till så alla I/O går från disk ("not found: read" på sista raden nedan).
Alltså lite drygt 3000 I/O per sekund från disk. Det som kallas "fetch for read" är
antalet databas sidor ("pages") som har kollats för att hitta tabellraderna. Notera
att dessa 3000 I/O per sekund inte går fysiskt mot disk, de fångas upp av OS'ets
diskcache och det var 3-400 I/O per sekund mot fysisk disk.

Kod: Markera allt

Node: xxxx (1/1/1)     Oracle Rdb V7.2-401 Perf. Monitor 14-FEB-2010 19:49:00.65
Rate: 1.00 Second         PIO Statistics--Data Fetches      Elapsed: 00:03:26.05
Page: 1 of 1          device:<yyyy.RDB_3>aaaa.RDB;5          Mode: Online
────────────────────────────────────────────────────────────────────────────────



statistic.........      rate.per.second............. total....... average......
name..............      max..... cur..... avg....... count....... per.trans....
fetch for read            226178   200623   155749.9     32093840           3.2
fetch for write                0        0        0.0            0           0.0
in AS: all ok             222802   197292   153262.2     31581210           3.1
   AS: need lock               0        0        0.0            0           0.0
   AS: old version             0        0        0.0            0           0.0
in GB: need lock               2        0        0.0            3           0.0
   GB: old version             0        0        0.0            0           0.0
   GB: transferred             0        0        0.0            0           0.0
not found: read             3484     3331     2487.7       512627           0.0
 synth                          0        0        0.0            0           0.0
Vad som är bra eller dåligt här kan vara lite svårt att säga. Det beror mycket
på miljön sm det hela körs i o.s.v.