sql >> Database teknologi >  >> RDS >> Mysql

Betyder jokertegn i kolonnen længst til venstre i det sammensatte indeks, at resterende kolonner i indekset ikke bruges i indeksopslag (MySQL)?

Her er dine spørgsmål. Flertal. Ved at omformulere dem (med "med andre ord") er de blot forskellige spørgsmål. At gøre det gør det ikke nødvendigvis nemmere for respondenterne. Tværtimod.

Q1:[Titelspørgsmål] Betyder jokertegn i kolonnen længst til venstre i det sammensatte indeks, at resterende kolonner i indekset ikke bruges i indeksopslag (MySQL)?

A1:Nej, det betyder ikke det.

Spørgsmål 2:Betyder jokertegnet, der bruges i last_name-tilstanden, at first_name-betingelsen ikke vil blive brugt til yderligere at hjælpe MySQL med at finde indekser?

A2:Nej, det betyder det ikke. Plus halen af ​​det spørgsmål er tvetydig. Den ved allerede, hvilket indeks, der skal bruges, kunne være et udløbersvar på en sådan vaghed.

Spørgsmål 3:Med andre ord, ved at sætte et jokertegn på efternavn-betingelsen vil MySQL kun lave et delvist indeksopslag (og ignorerer betingelser givet i kolonnerne, der er til højre for efternavn)?

A3:Nej. Kolonnerne længst til højre serveres fra indekset svarende til en dækkende indeksstrategi, der drager fordel af det langsomme datasideopslag.

Q4:... ville Eksempel-1 være hurtigere end Eksempel-2?

A4:Ja. Det er et dækkende indeks med hensyn til disse kolonner. Se dækkende indekser.

Som en sidebemærkning vedrørende Q4. Det er irrelevant, om det er en PK eller ikke-PK. Der er sikkert et dusin grunde til, at det som PK ville være forfærdeligt for din ansøgning.

Originale svar nedenfor:

med kun en sammensat nøgle på (last_name,first_name) og en forespørgsel som du nævner

WHERE first_name LIKE 'joh%'

... Den vil slet ikke bruge indekset. Det vil lave en tabelscanning. På grund af fraværet af

  • en enkelt kolonnenøgle på first_name
  • en sammensat nøgle med first_name længst til venstre

Så bordscanning her kommer vi.

Se venligst manualsiden Multiple-Column Indexes a> at læse mere. Og fokuser på left-most begrebet det. Faktisk, gå til den side og søg på ordet left .

Se manualsiden på Forklar facilitet i mysql. Også artiklen Brug Explain til at skrive bedre Mysql-forespørgsler .

Rediger

Der har været et par redigeringer af spørgsmålet, siden jeg var her for en time eller to siden. Jeg vil efterlade dig med følgende. Kør din faktiske forespørgsel gennem forklaring, og dechifrer gennem Using Explain ... link ovenfor eller en anden reference

drop table myNames;
create table myNames
(   id int auto_increment primary key,
    lastname varchar(100) not null,
    firstname varchar(100) not null,
    col4 int not null,
    key(lastname,firstname)
);
truncate table myNames;
insert myNames (lastName,firstName,col4) values
('Smith','John',1),('Smithers','JohnSomeone',1),('Smith3','John4324',1),('Smi','Jonathan',1),('Smith123x$FA','Joh',1),('Smi3jfif','jkdid',1),('r3','fe2',1);

insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;
insert myNames (lastName,firstName,col4) select lastname,firstname,col4 from mynames;

select count(*) from myNames; 
-- 458k rows

select count(*)
from myNames
where lastname like 'smi%';
-- 393216 rows

select count(*)
from myNames
where lastname like 'smi%' and firstname like 'joh%';
-- 262144 rows

Explain gengiver voodoo-tal for rows . Voodoo? Ja, fordi en forespørgsel, der potentielt kører i en time, beder du explain for at give dig et uklart tal, ikke køre det, og give dig det svar på 2 sekunder eller mindre. Betragt ikke disse for at være reelle antal #'er for kriterier, når det køres for rigtigt, uden explain .

explain 
select count(*) 
from myNames 
where lastname like 'smi%';
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows   | Extra                    |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | myNames | range | lastname      | lastname | 302     | NULL | 233627 | Using where; Using index |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+

explain 
select count(*) 
from myNames 
where lastname like 'smi%' and firstname like 'joh%' and col4=1;
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows   | Extra                    |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | myNames | range | lastname      | lastname | 604     | NULL | 233627 | Using where; Using index |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+


-- the below chunk is interest. Look at the Extra column

explain 
select count(*) 
from myNames 
where lastname like 'smi%' and firstname like 'joh%' and col4=1;
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table   | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | myNames | ALL  | lastname      | NULL | NULL    | NULL | 457932 | Using where |
+----+-------------+---------+------+---------------+------+---------+------+--------+-------------+

explain 
select count(*) 
from myNames 
where firstname like 'joh%';
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows   | Extra                    |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | myNames | index | NULL          | lastname | 604     | NULL | 453601 | Using where; Using index |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+


analyze table myNames;
+----------------------+---------+----------+----------+
| Table                | Op      | Msg_type | Msg_text |
+----------------------+---------+----------+----------+
| so_gibberish.mynames | analyze | status   | OK       |
+----------------------+---------+----------+----------+

select count(*) 
from myNames where left(lastname,3)='smi';
-- 393216 -- the REAL #
select count(*) 
from myNames where left(lastname,3)='smi' and left(firstname,3)='joh';
-- 262144 -- the REAL #

explain 
select lastname,firstname 
from myNames  
where lastname like 'smi%' and firstname like 'joh%';
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
| id | select_type | table   | type  | possible_keys | key      | key_len | ref  | rows   | Extra                    |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+
|  1 | SIMPLE      | myNames | range | lastname      | lastname | 604     | NULL | 226800 | Using where; Using index |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+


  1. MySQL FEJL 1045 (28000):Adgang nægtet for brugeren 'bill'@'localhost' (ved hjælp af adgangskode:JA)

  2. Hvordan får man Doctrine TEXT type?

  3. Er strengoperator "+" så enkel?

  4. MySqlDb kaster Operand skal indeholde 1 kolonne(r) på insert ignore statement