/ Forside / Teknologi / Udvikling / SQL / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
SQL
#NavnPoint
pmbruun 1704
niller 962
fehaar 730
Interkril.. 701
ellebye 510
pawel 510
rpje 405
pete 350
gibson 320
10  smorch 260
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

Søg
Reklame
Statistik
Spørgsmål : 177558
Tips : 31968
Nyheder : 719565
Indlæg : 6408925
Brugere : 218888

Månedens bedste
Årets bedste
Sidste års bedste