Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Bedeutet der Platzhalter in der linken Spalte des zusammengesetzten Index, dass die verbleibenden Spalten im Index nicht bei der Indexsuche (MySQL) verwendet werden?

Hier sind Ihre Fragen. Plural. Durch Umformulierung (mit "mit anderen Worten") sind es nur andere Fragen. Dies macht es den Respondern nicht unbedingt einfacher. Im Gegenteil.

F1:[Titelfrage] Bedeutet der Platzhalter in der linken Spalte des zusammengesetzten Index, dass die verbleibenden Spalten im Index bei der Indexsuche (MySQL) nicht verwendet werden?

A1:Nein, das bedeutet es nicht.

F2:Bedeutet der in der Bedingung „last_name“ verwendete Platzhalter, dass die Bedingung „first_name“ nicht verwendet wird, um MySQL weiter beim Finden von Indizes zu helfen?

A2:Nein, das bedeutet es nicht. Außerdem ist der Schwanz dieser Frage mehrdeutig. Es weiß bereits, welcher Index zu verwenden ist, könnte eine Ableger-Antwort auf eine solche Unbestimmtheit sein.

F3:Mit anderen Worten, MySQL führt durch Platzieren eines Platzhalters in der Nachname-Bedingung nur eine teilweise Indexsuche durch (und ignoriert Bedingungen, die in den Spalten rechts von Nachname angegeben sind)?

A3:Nein. Die Spalten ganz rechts werden aus dem Index bedient, ähnlich wie bei einer abdeckenden Indexstrategie, die von der Langsamkeit der Datenseitensuche profitiert.

F4:...wäre Beispiel-1 schneller als Beispiel-2?

A4:Ja. Es ist ein abdeckender Index in Bezug auf diese Spalten. Siehe abdeckende Indizes.

Nebenbei zu Q4. Dabei spielt es keine Rolle, ob es sich um eine PK oder eine Nicht-PK handelt. Es gibt wahrscheinlich ein Dutzend Gründe, warum das als PK für Ihre Anwendung schrecklich wäre.

Ursprüngliche Antwort(en) unten:

mit nur ein zusammengesetzter Schlüssel auf (last_name,first_name) und eine Abfrage, wie Sie erwähnt haben

WHERE first_name LIKE 'joh%'

... Der Index wird überhaupt nicht verwendet. Es wird ein Tabellenscan durchgeführt. Aufgrund des Fehlens von

  • ein einzelner Spaltenschlüssel auf first_name
  • ein zusammengesetzter Schlüssel mit first_name ganz links

Also Table Scan, wir kommen.

Bitte lesen Sie die Handbuchseite Mehrspaltige Indizes um mehr zu lesen. Und konzentrieren Sie sich auf left-most Konzept davon. Gehen Sie tatsächlich zu dieser Seite und suchen Sie nach dem Wort left .

Siehe Handbuchseite auf Explain Einrichtung in mysql. Auch der Artikel Using Explain to Write Better Mysql Queries .

Bearbeiten

Seit ich vor ein oder zwei Stunden hier war, wurden einige Änderungen an der Frage vorgenommen. Ich werde Sie mit dem Folgenden verlassen. Führen Sie Ihre eigentliche Abfrage durch EXPLAIN aus und entschlüsseln Sie sie durch Using Explain ... Link oben oder eine andere Referenz

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 rendert Voodoo-Zahlen für rows . Voodoo? Ja, denn eine Abfrage, die möglicherweise eine Stunde lang ausgeführt wird, fragen Sie nach explain um Ihnen eine Fuzzy-Zählung zu geben, es nicht auszuführen, und Ihnen diese Antwort in 2 Sekunden oder weniger zu geben. Betrachten Sie diese nicht als echte Zählnummern für Kriterien, wenn sie ohne explain in echt ausgeführt werden .

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 |
+----+-------------+---------+-------+---------------+----------+---------+------+--------+--------------------------+