| 
					
							
        
    
        
						
			 | 
			
			
					    
					
        
         
          
         
	
            | MySQL 5 - indexes Fra : Martin | 
  Dato :  25-04-09 02:44 |  
  |   
            Hvordan skal man lave de forskellige indexer, hvis man altså gerne vil
 have sin base indexeret.
 
 Det som jeg har er
 en users tabel
 en account_names tabel, med users_id som foreignkey til bruger tabellen
 en movements tabel med nøgle til konto navne tabellen
 
 en tabel med paytypes
 en tabel imellem movements og paytypes, så hver movement kan have flere
 paytypes.
 
 Skal jeg lave index'er på alle de de nøgler som referer til fremmednøglerne.
 (Det har jeg nu, ellers så kan man ikke lave innodb foreign keys)
 
 Fx
 ALTER TABLE `account_names` ADD INDEX `users_id` (`users_id`) ;
 og så fremdeles
 
 Alle tabeller er lige PT innodb, med foreign keys og on update/on delete
 Er dette smart at vælge den lidt langsommere innodb iforhold til myisam,
  der kommer ikke til at være nogle egentlige transactions
 
 I min movements tabel, som er den egentlige rigtige tabel med seriøst
 data i, der vil jeg gerne have feltet "info" (type: varchar 255) til at
 kunne klare hurtige LIKE '%...%' da der skal køre en trigger når der
 bliver indsat data i tabellen.
 
 Man kan også putte flere felter ind i ét index, hvad er formålet med
 dette Fx.
 ALTER TABLE `movements` ADD INDEX `testindex` (`withdraw_date`,
 `transfer_date`, `cost`) ;
 
 Jeg har også et view som ser således ud - her vil der komme nogle flere.
 
 select `m`.`id` AS `id`,`m`.`account_id` AS
 `account_id`,`m`.`withdraw_date` AS `withdraw_date`,`m`.`transfer_date`
 AS `transfer_date`,`m`.`info` AS `info`,`m`.`cost` AS `cost`,`m`.`saldo`
 AS `saldo`,`pt`.`id` AS `paytype_id`,`pt`.`name` AS `paytype_name` from
 ((`account`.`movements` `m` join `account`.`paytypes_to_account` `pa`
 on((`pa`.`movement_id` = `m`.`id`))) left join `account`.`paytypes` `pt`
 on((`pt`.`id` = `pa`.`paytype_id`)))
 
 Mit mål og ca. hvad jeg regner med at der kommer er data er:
 100 brugere, med hver 2 konto, og hver konto ca. 1500 movements, 10
 paytypes pr bruger.
 
 Så alt i alt vil der være følgende
 50 brugere
 100 konti
 150.000 movements
 100 paytypes
 (~50.000 i tabellen mellem movements og paytypes)
  
            
             |   |   
            
        
 
            
         
           Arne Vajhøj (25-04-2009) 
         
	
            | Kommentar Fra : Arne Vajhøj | 
  Dato :  25-04-09 03:09 |  
  |   
            Martin wrote:
 > Hvordan skal man lave de forskellige indexer, hvis man altså gerne vil
 > have sin base indexeret.
 > 
 > Det som jeg har er
 > en users tabel
 > en account_names tabel, med users_id som foreignkey til bruger tabellen
 > en movements tabel med nøgle til konto navne tabellen
 > 
 > en tabel med paytypes
 > en tabel imellem movements og paytypes, så hver movement kan have flere
 > paytypes.
 > 
 > Skal jeg lave index'er på alle de de nøgler som referer til fremmednøglerne.
 > (Det har jeg nu, ellers så kan man ikke lave innodb foreign keys)
 > 
 > Fx
 > ALTER TABLE `account_names` ADD INDEX `users_id` (`users_id`) ;
 > og så fremdeles
 
 Korrekte index kan godt være en kunst, men du går ikke helt ved
 siden ad med:
 - MySQL tilføjer selv automatisk et index på primary key
 - MySQL tvinger dig til at lave index på foreign keys hvis
    du definerer foreign key contraints på InnoDB tabeller
 - du laver så index på de felter som du bruger til udvælgelse
    (WHERE betingelser)
 - hvis der er nogen foreign keys som ikke er lavet som under
    pind #2, så laver du frivilligt index på dem
 
 > Alle tabeller er lige PT innodb, med foreign keys og on update/on delete
 > Er dette smart at vælge den lidt langsommere innodb iforhold til myisam,
 > der kommer ikke til at være nogle egentlige transactions
 
 Hvis du har nytte af foreign keys og performance er god nok, så
 lyder det da helt fint.
 
 > I min movements tabel, som er den egentlige rigtige tabel med seriøst
 > data i, der vil jeg gerne have feltet "info" (type: varchar 255) til at
 > kunne klare hurtige LIKE '%...%' da der skal køre en trigger når der
 > bliver indsat data i tabellen.
 
 LIKE '%...%' er aldrig hurtig da den ikke kan bruge et index.
 
 Måske kan du leve med performance af LIKE.
 
 Måske er fulltext index en mulighed.
 
 > Man kan også putte flere felter ind i ét index, hvad er formålet med
 > dette Fx.
 > ALTER TABLE `movements` ADD INDEX `testindex` (`withdraw_date`,
 > `transfer_date`, `cost`) ;
 
 Det kan der være flere grunde til.
 
 En mulighed er at det er en foreign key til en primary key
 i en anden tabel som består af 3 felter.
 
 Arne
  
            
             |   |   
            
        
 
            
         
           Martin (25-04-2009) 
         
	
            | Kommentar Fra : Martin | 
  Dato :  25-04-09 05:43 |  
  |   
            Arne Vajhøj wrote:
 > Korrekte index kan godt være en kunst, men du går ikke helt ved
 > siden ad med:
 > - MySQL tilføjer selv automatisk et index på primary key
 > - MySQL tvinger dig til at lave index på foreign keys hvis
 >   du definerer foreign key contraints på InnoDB tabeller
 > - du laver så index på de felter som du bruger til udvælgelse
 >   (WHERE betingelser)
 
 Altså bare alle felter som skal bruges i WHERE klausuler?
 
 > - hvis der er nogen foreign keys som ikke er lavet som under
 >   pind #2, så laver du frivilligt index på dem
 
 Ok.
 
 Nu tænker jeg bare lige liidt videre, hvorfor så ikke bare lave index på
 samtlige felter i databasen?
 
 > 
 >> Alle tabeller er lige PT innodb, med foreign keys og on update/on delete
 >> Er dette smart at vælge den lidt langsommere innodb iforhold til myisam,
 >> der kommer ikke til at være nogle egentlige transactions
 > 
 > Hvis du har nytte af foreign keys og performance er god nok, så
 > lyder det da helt fint.
 
 Nu har jeg faktisk kun lige bygget databasen med noget småligt data, så
 ved ikke hvordan performance er endnu.
 
 Er der egentlig en metode til at teste performance på, altså uden at
 kigge i slow query logfilen? (og uden at have flere tusinde test rækker)
 
 > 
 >> I min movements tabel, som er den egentlige rigtige tabel med seriøst
 >> data i, der vil jeg gerne have feltet "info" (type: varchar 255) til at
 >> kunne klare hurtige LIKE '%...%' da der skal køre en trigger når der
 >> bliver indsat data i tabellen.
 > 
 > LIKE '%...%' er aldrig hurtig da den ikke kan bruge et index.
 
 Nej, det vidste jeg egentlig godt.
 
 > 
 > Måske kan du leve med performance af LIKE.
 > 
 > Måske er fulltext index en mulighed.
 
 Se.. troede faktisk kun man kunne have fulltext på TEXT/LONGTEXT felter,
 men kan se man også kan have på varchar felter, så det kunne være en
 rigtig god mulighed.
 
 > 
 >> Man kan også putte flere felter ind i ét index, hvad er formålet med
 >> dette Fx.
 >> ALTER TABLE `movements` ADD INDEX `testindex` (`withdraw_date`,
 >> `transfer_date`, `cost`) ;
 > 
 > Det kan der være flere grunde til.
 > 
 > En mulighed er at det er en foreign key til en primary key
 > i en anden tabel som består af 3 felter.
 
 Kan du give et mini eksempel, tror ikke jeg lige forstod dette.
  
            
             |   |   
            
        
 
            
         
            Peter Lykkegaard (25-04-2009) 
         
	
            | Kommentar Fra : Peter Lykkegaard | 
  Dato :  25-04-09 07:50 |  
  |   
            Martin skrev
 
 > Altså bare alle felter som skal bruges i WHERE klausuler?
 >
 Vær opmærksom på at få dokumenteret dine indexes/where clauses
 Rækken af felter skal matche esakt for at få glæde af dine indexes
 
 Eg et index med fornavn, efternavn bliver ikke brugt hvis din where clause 
 bruger efternavn, fornavn elller blot efternavn
 
 - Peter
  
 
 
  
            
             |   |   
            
        
 
            
         
             Leif Neland (25-04-2009) 
         
	
            | Kommentar Fra : Leif Neland | 
  Dato :  25-04-09 17:38 |  
  |   
            Peter Lykkegaard skrev:
 > Martin skrev
 > 
 >> Altså bare alle felter som skal bruges i WHERE klausuler?
 >>
 > Vær opmærksom på at få dokumenteret dine indexes/where clauses
 > Rækken af felter skal matche esakt for at få glæde af dine indexes
 > 
 > Eg et index med fornavn, efternavn bliver ikke brugt hvis din where clause 
 > bruger efternavn, fornavn elller blot efternavn
 > 
 
 Rækkefølgen af where er ligegyldig, optimizeren kan godt se hvilke 
 felter der bruges.
 
 Et index på fornavn, efternavn kan også bruges, når der kun søges på 
 fornavn.
 
 Leif
  
            
             |   |   
            
        
 
            
         
             N/A (26-04-2009) 
         
	
            | Kommentar Fra : N/A | 
  Dato :  26-04-09 16:04 |  
  |   
            
  
            
             |   |   
            
        
 
            
         
            Arne Vajhøj (25-04-2009) 
         
	
            | Kommentar Fra : Arne Vajhøj | 
  Dato :  25-04-09 13:32 |  
  |   
            Martin wrote:
 > Arne Vajhøj wrote:
 >> Korrekte index kan godt være en kunst, men du går ikke helt ved
 >> siden ad med:
 >> - MySQL tilføjer selv automatisk et index på primary key
 >> - MySQL tvinger dig til at lave index på foreign keys hvis
 >>   du definerer foreign key contraints på InnoDB tabeller
 >> - du laver så index på de felter som du bruger til udvælgelse
 >>   (WHERE betingelser)
 > 
 > Altså bare alle felter som skal bruges i WHERE klausuler?
 
 Ja.
 
 >> - hvis der er nogen foreign keys som ikke er lavet som under
 >>   pind #2, så laver du frivilligt index på dem
 > 
 > Ok.
 > 
 > Nu tænker jeg bare lige liidt videre, hvorfor så ikke bare lave index på
 > samtlige felter i databasen?
 
 Hver gang du tilføjer et index, så tilføjer du overhead til INSERT.
 
 Men specielt for begyndere vil jeg sige: hellere et index for meget
 end et index for lidt.
 
 >>> Alle tabeller er lige PT innodb, med foreign keys og on update/on delete
 >>> Er dette smart at vælge den lidt langsommere innodb iforhold til myisam,
 >>> der kommer ikke til at være nogle egentlige transactions
 >> Hvis du har nytte af foreign keys og performance er god nok, så
 >> lyder det da helt fint.
 > 
 > Nu har jeg faktisk kun lige bygget databasen med noget småligt data, så
 > ved ikke hvordan performance er endnu.
 > 
 > Er der egentlig en metode til at teste performance på, altså uden at
 > kigge i slow query logfilen? (og uden at have flere tusinde test rækker)
 
 Med kun tusinder af rækker kan jeg næste garantere at performance er OK.
 
 Hundredevis af millioner eller milliarder rækker, så skal vi til at
 tune.
 
 >>> Man kan også putte flere felter ind i ét index, hvad er formålet med
 >>> dette Fx.
 >>> ALTER TABLE `movements` ADD INDEX `testindex` (`withdraw_date`,
 >>> `transfer_date`, `cost`) ;
 >> Det kan der være flere grunde til.
 >>
 >> En mulighed er at det er en foreign key til en primary key
 >> i en anden tabel som består af 3 felter.
 > 
 > Kan du give et mini eksempel, tror ikke jeg lige forstod dette.
 
 Lad os sige at du har en person tabel med en primary key sammensat
 af 3 felter (fornavn, mellemnavn, efternavn) og har en anden tabel
 som skal have en foreign key som peger på person tabellen.
 
 (det er ikke et specielt godt database design, men ...)
 
 Arne
  
            
             |   |   
            
        
 
            
         
             Peter Lykkegaard (25-04-2009) 
         
	
            | Kommentar Fra : Peter Lykkegaard | 
  Dato :  25-04-09 13:58 |  
  |   
            Arne Vajhøj
 >
 > Hundredevis af millioner eller milliarder rækker, så skal vi til at
 > tune.
 
 Eller rigtig mange requests/inserts/updates i minuttet ...
 
 - Peter 
 
 
  
            
             |   |   
            
        
 
            
         
             Stig Johansen (25-04-2009) 
         
	
            | Kommentar Fra : Stig Johansen | 
  Dato :  25-04-09 22:48 |  
  |   
            Arne Vajhøj wrote:
 
 > Hver gang du tilføjer et index, så tilføjer du overhead til INSERT.
 > 
 > Men specielt for begyndere vil jeg sige: hellere et index for meget
 > end et index for lidt.
 
 Jeg ville nok anbefale det modsatte, at vælge færrest mulige som
 udgangspunkt.
 
 Som du selv skriver, så er incicies et tradeoff mellem læsninger og
 skrivninger.
 
 Men de fleste databasesystemer har en funktion til at aflæse hvad
 optimizeren har tænkt sig at gøre, så..
 >> Er der egentlig en metode til at teste performance på, altså uden at
 >> kigge i slow query logfilen? 
 
 i mySQL hedder den (metoden) åbenbart EXPLAIN.
 
 >> (og uden at have flere tusinde test rækker) 
 
 Her må svaret være nej, da nogle databaser tager hensyn til størrelsen af
 datasættet, og kan vælge et tablescan frem for at bruge indicies.
 
 Database 'tuning' er dynamisk, og ikke statisk.
 
 -- 
 Med venlig hilsen
 Stig Johansen
  
            
             |   |   
            
        
 
            
         
              Arne Vajhøj (26-04-2009) 
         
	
            | Kommentar Fra : Arne Vajhøj | 
  Dato :  26-04-09 18:34 |  
  |   
            Stig Johansen wrote:
 > Arne Vajhøj wrote:
 >> Hver gang du tilføjer et index, så tilføjer du overhead til INSERT.
 >>
 >> Men specielt for begyndere vil jeg sige: hellere et index for meget
 >> end et index for lidt.
 > 
 > Jeg ville nok anbefale det modsatte, at vælge færrest mulige som
 > udgangspunkt.
 
 Så risikerer man at queries kører x100 for langsomt. Insert overhead
 er langt mindre.
 
 Arne
  
            
             |   |   
            
        
 
            
         
               Leif Neland (26-04-2009) 
         
	
            | Kommentar Fra : Leif Neland | 
  Dato :  26-04-09 22:29 |  
  |   
            Arne Vajhøj skrev:
 > Stig Johansen wrote:
 >> Arne Vajhøj wrote:
 >>> Hver gang du tilføjer et index, så tilføjer du overhead til INSERT.
 >>>
 >>> Men specielt for begyndere vil jeg sige: hellere et index for meget
 >>> end et index for lidt.
 >>
 >> Jeg ville nok anbefale det modsatte, at vælge færrest mulige som
 >> udgangspunkt.
 > 
 > Så risikerer man at queries kører x100 for langsomt. Insert overhead
 > er langt mindre.
 > 
 Så skal der også tages højde for om der er mange inserts og få queries, 
 f.ex. logning, eller få inserts og mange queries, f.ex. en database til 
 en webside.
 
 Leif
  
            
             |   |   
            
        
 
            
         
                Arne Vajhøj (27-04-2009) 
         
	
            | Kommentar Fra : Arne Vajhøj | 
  Dato :  27-04-09 01:38 |  
  |   
            Leif Neland wrote:
 > Arne Vajhøj skrev:
 >> Stig Johansen wrote:
 >>> Arne Vajhøj wrote:
 >>>> Hver gang du tilføjer et index, så tilføjer du overhead til INSERT.
 >>>>
 >>>> Men specielt for begyndere vil jeg sige: hellere et index for meget
 >>>> end et index for lidt.
 >>>
 >>> Jeg ville nok anbefale det modsatte, at vælge færrest mulige som
 >>> udgangspunkt.
 >>
 >> Så risikerer man at queries kører x100 for langsomt. Insert overhead
 >> er langt mindre.
 >>
 > Så skal der også tages højde for om der er mange inserts og få queries, 
 > f.ex. logning, eller få inserts og mange queries, f.ex. en database til 
 > en webside.
 
 En tommelfinger regel som den er kun relevant for begyndere.
 
 Når folk begynder at overveje insert/select ratios og studere
 explain output, så har de ikke brug for en tommelfinger regel.
 
 Arne
  
            
             |   |   
            
        
 
            
         
                 Stig Johansen (27-04-2009) 
         
	
            | Kommentar Fra : Stig Johansen | 
  Dato :  27-04-09 05:23 |  
  |   
            Arne Vajhøj wrote:
 
 > En tommelfinger regel som den er kun relevant for begyndere.
 
 Jo, men du skrev:
 > Men specielt for begyndere vil jeg sige: hellere et index for meget
 > end et index for lidt.
 
 Og der er vi uenige om hvilken anbefaling man skal give begyndere.
 Du vil anbefale flest mulige indexes, hvorefter man risikerer at ende med en
 masse overflødige indexer.
 
 Jeg vil anbefale færrest mulige, så man kun har de nødvendige indexer.
 Bemærk, at jeg ikke mener 'ingen indexer' som udgangspunkt, men nærmere 'de
 åbenlyse'.
 
 Hvis man efterfølgende oplever performanceproblemer på specifikke queries,
 kan man begynde at tune på dem.
 
 Det er nok subjektivt hvilken retning man mener er den rette (for
 begyndere), og subjektive ting bliver man nok aldrig enige om.
 
 Men datamænger og evt. performanceproblemer er nok ikke relevant for
 begyndere (tror jeg).
 
 -- 
 Med venlig hilsen
 Stig Johansen
  
            
             |   |   
            
        
 
            
         
           Peter Lykkegaard (26-04-2009) 
         
	
            | Kommentar Fra : Peter Lykkegaard | 
  Dato :  26-04-09 02:34 |  
  |   
            Leif Neland skrev
 
 > Et index på fornavn, efternavn kan også bruges, når der kun søges på
 > fornavn.
 >
 Ja jeg har forhåbentligt ikke påstået andet?
 
 Men prøv at undersøge hvad der sker hvis du bruger efternavn, fornavn
 eller efternavn
 
 - Peter
  
            
             |   |   
            
        
 
            
         
            Leif Neland (26-04-2009) 
         
	
            | Kommentar Fra : Leif Neland | 
  Dato :  26-04-09 11:34 |  
  |   
            Peter Lykkegaard wrote:
 > Leif Neland skrev
 >
 >> Et index på fornavn, efternavn kan også bruges, når der kun søges på
 >> fornavn.
 >>
 > Ja jeg har forhåbentligt ikke påstået andet?
 >
 Nej, men du påstår:
 
 >>Vær opmærksom på at få dokumenteret dine indexes/where clauses
 >>Rækken af felter skal matche esakt for at få glæde af dine indexes
 
 >>Eg et index med fornavn, efternavn bliver ikke brugt hvis din where clause
 >>bruger efternavn, fornavn ...
 
 Og det siger jeg er forkert.
 
 Leif 
 
 
  
            
             |   |   
            
        
 
            
         
            N/A (26-04-2009) 
         
	
            | Kommentar Fra : N/A | 
  Dato :  26-04-09 16:04 |  
  |   
            
  
            
             |   |   
            
        
 
            
         
           Peter Lykkegaard (26-04-2009) 
         
	
            | Kommentar Fra : Peter Lykkegaard | 
  Dato :  26-04-09 05:52 |  
  |  
 
            Leif Neland skrev
 >
 > Nej, men du påstår:
 >
 > >>Vær opmærksom på at få dokumenteret dine indexes/where clauses
 > >>Rækken af felter skal matche esakt for at få glæde af dine indexes
 > >>Eg et index med fornavn, efternavn bliver ikke brugt hvis din where clause
 > >>bruger efternavn, fornavn ...
 >
 > Og det siger jeg er forkert.
 >
 Fair enough
 Hvilket databasesystem?
 OP nævner MySQL jeg går ud fra at det er det samme system du tænker
 på?
 Har du undersøgt hvad optimizeren laver vha explain?
 Kikker man i manualen til MYSQL så er min påstand korrekt i forhold
 til den officilelle dokumentation
 http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
"MySQL cannot use an index if the columns do not form a leftmost
 prefix of the index. Suppose that you have the SELECT statements shown
 here:
 SELECT * FROM tbl_name WHERE col1=val1;
 SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
 SELECT * FROM tbl_name WHERE col2=val2;
 SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
 If an index exists on (col1, col2, col3), only the first two queries
 use the index. The third and fourth queries do involve indexed
 columns, but (col2) and (col2, col3) are not leftmost prefixes of
 (col1, col2, col3). "
 Typisk bliver et index gemt i en b-tree konstruktion og det vil også
 forklare hvorfor din "ide" *ikke* kan lade sig gøre :)
 - Peter
            
              |   |   
            
        
 
            
         
            Arne Vajhøj (26-04-2009) 
         
	
            | Kommentar Fra : Arne Vajhøj | 
  Dato :  26-04-09 16:04 |  
  |  
 
            Peter Lykkegaard wrote:
 > Leif Neland skrev
 >> Nej, men du påstår:
 >>>> Vær opmærksom på at få dokumenteret dine indexes/where clauses
 >>>> Rækken af felter skal matche esakt for at få glæde af dine indexes
 >>>> Eg et index med fornavn, efternavn bliver ikke brugt hvis din where clause
 >>>> bruger efternavn, fornavn ...
 >> Og det siger jeg er forkert.
 > Kikker man i manualen til MYSQL så er min påstand korrekt i forhold
 > til den officilelle dokumentation
 >  http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html
> 
 > "MySQL cannot use an index if the columns do not form a leftmost
 > prefix of the index. Suppose that you have the SELECT statements shown
 > here:
 > SELECT * FROM tbl_name WHERE col1=val1;
 > SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
 > 
 > SELECT * FROM tbl_name WHERE col2=val2;
 > SELECT * FROM tbl_name WHERE col2=val2 AND col3=val3;
 > If an index exists on (col1, col2, col3), only the first two queries
 > use the index. The third and fourth queries do involve indexed
 > columns, but (col2) and (col2, col3) are not leftmost prefixes of
 > (col1, col2, col3). "
 Prøv lige og læs hvad du skrev og hvad der står i manualen en gang
 til.
 Der er intet i det du citerer som underbygger din påstand.
 Hvis manualen havde sagt at indexet ikke kunen bruges ved
 SELECT * FROM tbl_name WHERE col2=val2 AND col1=val1;
 så havde det underbygget din påstand.
 Men det gør den ikke.
 Arne
            
              |   |   
            
        
 
            
         
            N/A (26-04-2009) 
         
	
            | Kommentar Fra : N/A | 
  Dato :  26-04-09 18:31 |  
  |   
            
  
            
             |   |   
            
        
 
            
         
           N/A (26-04-2009) 
         
	
            | Kommentar Fra : N/A | 
  Dato :  26-04-09 16:04 |  
  |   
            
  
            
             |   |   
            
        
 
            
         
           Peter Lykkegaard (26-04-2009) 
         
	
            | Kommentar Fra : Peter Lykkegaard | 
  Dato :  26-04-09 09:35 |  
  |   
            Arne Vajhøj skrev
 
 > Der er intet i det du citerer som underbygger din påstand.
 >
 "MySQL cannot use an index if the columns do not form a leftmost
 prefix of the index"
 
 > Hvis manualen havde sagt at indexet ikke kunen bruges ved
 >
 > SELECT * FROM tbl_name WHERE col2=val2 AND col1=val1;
 >
 Manualen skriver at SELECT * FROM tbl_name WHERE col2=val2 ikke bruger
 index der består af col1, col2
 
 Kan optimizeren finde ud af at bytte rundt på col2 og col1?
 MSSQL kan ikke svjv og imo er det lidt i modstrid mod sætningen
 ovenfor, eller?
 
 - Peter
  
            
             |   |   
            
        
 
            
         
            Andreas Plesner Jaco~ (26-04-2009) 
         
	
            | Kommentar Fra : Andreas Plesner Jaco~ | 
  Dato :  26-04-09 16:40 |  
  |   
            On 2009-04-26, Peter Lykkegaard <plykkegaard@gmail.com> wrote:
 >
 > Kan optimizeren finde ud af at bytte rundt på col2 og col1?
 
 Ja. Hvorfor gætte når man kan teste på et øjeblik?
 
 mysql> create table test (col1 varchar(8), col2 varchar(8));
 Query OK, 0 rows affected (0.25 sec)
 
 mysql> insert into test values ('col1_1', 'col2_1');
 Query OK, 1 row affected (0.00 sec)
 
 mysql> insert into test values ('col1_2', 'col2_2');
 Query OK, 1 row affected (0.00 sec)
 
 mysql> create index testidx on test (col1, col2);
 Query OK, 2 rows affected (0.18 sec)
 Records: 2  Duplicates: 0  Warnings: 0
 
 mysql> explain select * from test where col1 = 'col1_2' and col2 =
 'col2_2';
 +----+-------------+-------+------+---------------+---------+---------+-------------+------+--------------------------+
 | id | select_type | table | type | possible_keys | key     | key_len |
 ref         | rows | Extra                    |
 +----+-------------+-------+------+---------------+---------+---------+-------------+------+--------------------------+
 |  1 | SIMPLE      | test  | ref  | testidx       | testidx | 22      |
 const,const |    1 | Using where; Using index | 
 +----+-------------+-------+------+---------------+---------+---------+-------------+------+--------------------------+
 1 row in set (0.00 sec)
 
 mysql> explain select * from test where col2 = 'col2_2' and col1 =
 'col1_2';
 +----+-------------+-------+------+---------------+---------+---------+-------------+------+--------------------------+
 | id | select_type | table | type | possible_keys | key     | key_len |
 ref         | rows | Extra                    |
 +----+-------------+-------+------+---------------+---------+---------+-------------+------+--------------------------+
 |  1 | SIMPLE      | test  | ref  | testidx       | testidx | 22      |
 const,const |    1 | Using where; Using index | 
 +----+-------------+-------+------+---------------+---------+---------+-------------+------+--------------------------+
 1 row in set (0.00 sec)
 
 -- 
 Andreas
  
            
             |   |   
            
        
 
            
         
             Stig Johansen (27-04-2009) 
         
	
            | Kommentar Fra : Stig Johansen | 
  Dato :  27-04-09 11:16 |  
  |   
            "Andreas Plesner Jacobsen" <apj@daarligstil.dk> wrote in message
 news:slrngv9032.krr.apj@irq.hestdesign.com...
 > On 2009-04-26, Peter Lykkegaard <plykkegaard@gmail.com> wrote:
 > >
 > > Kan optimizeren finde ud af at bytte rundt på col2 og col1?
 >
 > Ja. Hvorfor gætte når man kan teste på et øjeblik?
 
 Præcis, men jeg vil nok ikke bruge ordet 'gætte', når man kan afprøve ting.
 
 Lige for tiden kigger jeg lidt på SQLite, og en 'Explain' ser sådan ud
 (p.t):
 ......
 addr(INT);opcode(TEXT);p1(INT);p2(INT);p3(INT);p4(TEXT);p5(TEXT);comment(NUL
 L)
 0;Trace;0;0;0;explain select * from test where col2 =
 'col2_2' and col1 = 'col1_2'
 ;00;.NULL.
 1;String8;0;1;0;col2_2;00;.NULL.
 2;String8;0;2;0;col1_2;00;.NULL.
 3;Goto;0;19;0;;00;.NULL.
 4;SetNumColumns;0;3;0;;00;.NULL.
 5;OpenRead;1;3;0;keyinfo(2,BINARY,BINARY);00;.NULL.
 6;SCopy;2;4;0;;00;.NULL.
 7;IsNull;4;17;0;;00;.NULL.
 8;SCopy;1;5;0;;00;.NULL.
 9;IsNull;5;17;0;;00;.NULL.
 10;MakeRecord;4;2;3;aab;00;.NULL.
 11;MoveGe;1;17;3;;00;.NULL.
 12;IdxGE;1;17;3;;01;.NULL.
 13;Column;1;0;8;;00;.NULL.
 14;Column;1;1;9;;00;.NULL.
 15;ResultRow;8;2;0;;00;.NULL.
 16;Next;1;12;0;;00;.NULL.
 17;Close;1;0;0;;00;.NULL.
 18;Halt;0;0;0;;00;.NULL.
 19;Transaction;0;0;0;;00;.NULL.
 20;VerifyCookie;0;4;0;;00;.NULL.
 21;TableLock;0;2;0;test;00;.NULL.
 22;Goto;0;4;0;;00;.NULL.
 .......
 Hvor statementet jfr. tråden var:
 explain select * from test where col2 ='col2_2' and col1 = 'col1_2'
 Med diverse indexes.
 --
 Med venlig hilsen/Best regards
 Stig Johansen
 
 
 
  
            
             |   |   
            
        
 
            
         
            Arne Vajhøj (26-04-2009) 
         
	
            | Kommentar Fra : Arne Vajhøj | 
  Dato :  26-04-09 18:31 |  
  |   
            Peter Lykkegaard wrote:
 > Arne Vajhøj skrev
 >> Der er intet i det du citerer som underbygger din påstand.
 >>
 > "MySQL cannot use an index if the columns do not form a leftmost
 > prefix of the index"
 
 Ja.
 
 Og det underbygger ikke din påstand:
 
 #Eg et index med fornavn, efternavn bliver ikke brugt hvis din where clause
 #bruger efternavn, fornavn
 
 >> Hvis manualen havde sagt at indexet ikke kunen bruges ved
 >>
 >> SELECT * FROM tbl_name WHERE col2=val2 AND col1=val1;
 >>
 > Manualen skriver at SELECT * FROM tbl_name WHERE col2=val2 ikke bruger
 > index der består af col1, col2
 
 Ja. Men det er en helt anden problem stilling.
 
 > Kan optimizeren finde ud af at bytte rundt på col2 og col1?
 
 Det vil jeg tro.
 
 > MSSQL kan ikke svjv og imo er det lidt i modstrid mod sætningen
 > ovenfor, eller?
 
 Ikke spor.
 
 Arne
  
            
             |   |   
            
        
 
            
         
            Leif Neland (26-04-2009) 
         
	
            | Kommentar Fra : Leif Neland | 
  Dato :  26-04-09 19:41 |  
  |   
            Peter Lykkegaard skrev:
 > Arne Vajhøj skrev
 > 
 >> Der er intet i det du citerer som underbygger din påstand.
 >>
 > "MySQL cannot use an index if the columns do not form a leftmost
 > prefix of the index"
 > 
 >> Hvis manualen havde sagt at indexet ikke kunen bruges ved
 >>
 >> SELECT * FROM tbl_name WHERE col2=val2 AND col1=val1;
 >>
 > Manualen skriver at SELECT * FROM tbl_name WHERE col2=val2 ikke bruger
 > index der består af col1, col2
 > 
 > Kan optimizeren finde ud af at bytte rundt på col2 og col1?
 > MSSQL kan ikke svjv og imo er det lidt i modstrid mod sætningen
 > ovenfor, eller?
 > 
 
 Hvis en optimizer ikke kan finde ud af at
 SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
 SELECT * FROM tbl_name WHERE col2=val2 AND col1=val1;
 er det samme udtryk, så fortjener den ikke navnet optimizer...
 
 Leif
  
            
             |   |   
            
        
 
            
         
             Arne Vajhøj (27-04-2009) 
         
	
            | Kommentar Fra : Arne Vajhøj | 
  Dato :  27-04-09 01:46 |  
  |   
            Leif Neland wrote:
 > Peter Lykkegaard skrev:
 >> Arne Vajhøj skrev
 >>
 >>> Der er intet i det du citerer som underbygger din påstand.
 >>>
 >> "MySQL cannot use an index if the columns do not form a leftmost
 >> prefix of the index"
 >>
 >>> Hvis manualen havde sagt at indexet ikke kunen bruges ved
 >>>
 >>> SELECT * FROM tbl_name WHERE col2=val2 AND col1=val1;
 >>>
 >> Manualen skriver at SELECT * FROM tbl_name WHERE col2=val2 ikke bruger
 >> index der består af col1, col2
 >>
 >> Kan optimizeren finde ud af at bytte rundt på col2 og col1?
 >> MSSQL kan ikke svjv og imo er det lidt i modstrid mod sætningen
 >> ovenfor, eller?
 >>
 > 
 > Hvis en optimizer ikke kan finde ud af at
 > SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
 > SELECT * FROM tbl_name WHERE col2=val2 AND col1=val1;
 > er det samme udtryk, så fortjener den ikke navnet optimizer...
 
 Så vidt jeg lige kan gennemskue SQLServer output så
 kan den fint finde ud af det:
 
 1> create table test (col1 varchar(8), col2 varchar(8))
 2> go
 1>
 2> insert into test values ('col1_1', 'col2_1')
 3> go
 (1 row affected)
 1> insert into test values ('col1_2', 'col2_2')
 2> go
 (1 row affected)
 1>
 2> create index testidx on test (col1, col2)
 3> go
 1>
 2> set showplan_all on
 3> go
 1>
 2> select * from test where col1 = 'col1_2' and col2 = 'col2_2'
 3> go
   StmtText
 
 
          StmtId      NodeId      Parent      PhysicalOp
          LogicalOp
          Argument
 
 
          DefinedValues 
 EstimateRows
          EstimateIO     EstimateCPU    AvgRowSize  TotalSubtreeCost
          OutputList                                              Warnings
          Type
          Parallel EstimateExecutions
  
 -------------------------------------------------------------------------------
 
  
 ---------------------------------------------------------------------
          ----------- ----------- ----------- ------------------------------
          ------------------------------
  
 ------------------------------------------------------------------------
 
          -----------------------------------------------------------
          ------------------------------------------------------- 
 --------------
          -------------- -------------- ----------- ----------------
          ------------------------------------------------------- --------
          ----------------------------------------------------------------
          -------- ------------------
 
 select * from test where col1 = 'col1_2' and col2 = 'col2_2'
 
                    1           1           0 NULL
          NULL
          1
 
 
          NULL 
      1.0
                    NULL           NULL        NULL        0.0032831
          NULL                                                    NULL
          SELECT
                 0               NULL
     |--Index Seek(OBJECT:([Test].[dbo].[test].[testidx]), 
 SEEK:([Test].[dbo].[tes
 
          t].[col1]=[@1] AND [Test].[dbo].[test].[col2]=[@2]) ORDERED 
 FORWARD)
                    1           2           1 Index Seek
          Index Seek
          OBJECT:([Test].[dbo].[test].[testidx]), 
 SEEK:([Test].[dbo].[test].[col1]
 
          =[@1] AND [Test].[dbo].[test].[col2]=[@2]) ORDERED FORWARD
          [Test].[dbo].[test].[col1], [Test].[dbo].[test].[col2] 
      1.0
                0.003125      0.0001581          25        0.0032831
          [Test].[dbo].[test].[col1], [Test].[dbo].[test].[col2]  NULL
          PLAN_ROW
                 0                1.0
 
 (2 rows affected)
 1>
 2> select * from test where col2 = 'col2_2' and col1 = 'col1_2'
 3> go
   StmtText
 
 
          StmtId      NodeId      Parent      PhysicalOp
          LogicalOp
          Argument
 
 
          DefinedValues 
 EstimateRows
          EstimateIO     EstimateCPU    AvgRowSize  TotalSubtreeCost
          OutputList                                              Warnings
          Type
          Parallel EstimateExecutions
  
 -------------------------------------------------------------------------------
 
  
 ---------------------------------------------------------------------
          ----------- ----------- ----------- ------------------------------
          ------------------------------
  
 ------------------------------------------------------------------------
 
          -----------------------------------------------------------
          ------------------------------------------------------- 
 --------------
          -------------- -------------- ----------- ----------------
          ------------------------------------------------------- --------
          ----------------------------------------------------------------
          -------- ------------------
 
 select * from test where col2 = 'col2_2' and col1 = 'col1_2'
 
                    1           1           0 NULL
          NULL
          1
 
 
          NULL 
      1.0
                    NULL           NULL        NULL        0.0032831
          NULL                                                    NULL
          SELECT
                 0               NULL
     |--Index Seek(OBJECT:([Test].[dbo].[test].[testidx]), 
 SEEK:([Test].[dbo].[tes
 
          t].[col1]=[@2] AND [Test].[dbo].[test].[col2]=[@1]) ORDERED 
 FORWARD)
                    1           2           1 Index Seek
          Index Seek
          OBJECT:([Test].[dbo].[test].[testidx]), 
 SEEK:([Test].[dbo].[test].[col1]
 
          =[@2] AND [Test].[dbo].[test].[col2]=[@1]) ORDERED FORWARD
          [Test].[dbo].[test].[col1], [Test].[dbo].[test].[col2] 
      1.0
                0.003125      0.0001581          25        0.0032831
          [Test].[dbo].[test].[col1], [Test].[dbo].[test].[col2]  NULL
          PLAN_ROW
                 0                1.0
 
 (2 rows affected)
 1>
 2> set showplan_all off
 3> go
 1>
 2> drop table test
 3> go
 
 Arne
  
            
             |   |   
            
        
 
            
         
           Peter Lykkegaard (26-04-2009) 
         
	
            | Kommentar Fra : Peter Lykkegaard | 
  Dato :  26-04-09 09:55 |  
  |   
            Andreas Plesner Jacobsen skrev
 
 > Ja.
 
 Tak :)
 
 Det må jeg lige prøve på mssql ved lejlighed
 
 - Peter
  
            
             |   |   
            
        
 
    
 
					
					 
			 | 
			
				
        
			 |