【发布时间】:2016-05-14 10:48:22
【问题描述】:
下面的解释我看不懂:
第一个仅涉及 PAZIENTE 和 ANALISI, 没关系,它正在使用索引 IDX_NOME
explain
select
paziente3_.cognome as col_8_0_
from
Analisi analisi0_
inner join
Paziente paziente3_
on analisi0_.ID_PAZIENTE=paziente3_.ID_PAZIENTE
where
paziente3_.nome like 'MARCO%';
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE paziente3_ range PRIMARY,IDX_NOME IDX_NOME 123 1350 100 Using where; Using index
1 SIMPLE analisi0_ ref FK_ANALISI_PAZIENTE FK_ANALISI_PAZIENTE 4 gestelfolab.paziente3_.ID_PAZIENTE 1 100 Using index
如果在同一个查询中,我也尝试检索 SPECIE 描述,索引 IDX_NOME 不再使用,并且存在全表扫描,
explain
select
specie5_.specie as col_5_0_,
paziente3_.cognome as col_8_0_
from
Analisi analisi0_
inner join
Paziente paziente3_
on analisi0_.ID_PAZIENTE=paziente3_.ID_PAZIENTE
inner join
Specie specie5_
on paziente3_.ID_SPECIE=specie5_.ID_SPECIE
where
paziente3_.nome like 'MARCO%';
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE specie5_ index PRIMARY SPECIE 137 1 100 Using index
1 SIMPLE paziente3_ ALL PRIMARY,IDX_NOME,FK_PAZIENTE_SPECIE 176184 10 Range checked for each record (index map: 0x19)
1 SIMPLE analisi0_ ref FK_ANALISI_PAZIENTE FK_ANALISI_PAZIENTE 4 gestelfolab.paziente3_.ID_PAZIENTE 1 100 Using index
是不是表定义出错了?
CREATE TABLE SPECIE
(
ID_SPECIE TINYINT UNSIGNED NOT NULL AUTO_INCREMENT,
SPECIE VARCHAR(45) NOT NULL UNIQUE,
PRIMARY KEY (ID_SPECIE)
)
ENGINE=InnoDB;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
specie 0 PRIMARY 1 ID_SPECIE A 0 BTREE
specie 0 SPECIE 1 SPECIE A 0 BTREE
CREATE TABLE PAZIENTE
(
ID_PAZIENTE INT UNSIGNED NOT NULL AUTO_INCREMENT,
ID_PAZIENTE_LAB VARCHAR(20),
COGNOME VARCHAR(40),
NOME VARCHAR(40),
DATA_NASCITA DATE,
ID_SESSO TINYINT UNSIGNED NOT NULL,
RECAPITO VARCHAR(50),
CODICE_FISCALE VARCHAR(30),
ID_SPECIE TINYINT UNSIGNED NOT NULL,
PRIMARY KEY (ID_PAZIENTE),
INDEX IDX_DATA_NASCITA (DATA_NASCITA, ID_SESSO, ID_SPECIE),
INDEX IDX_COGNOME (COGNOME, NOME, ID_SESSO, ID_SPECIE),
INDEX IDX_NOME (NOME, COGNOME, ID_SESSO, ID_SPECIE),
CONSTRAINT FK_PAZIENTE_SPECIE FOREIGN KEY (ID_SPECIE) REFERENCES SPECIE(ID_SPECIE),
CONSTRAINT FK_PAZIENTE_SESSO FOREIGN KEY (ID_SESSO) REFERENCES SESSO(ID_SESSO)
)
ENGINE=InnoDB;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment
paziente 0 PRIMARY 1 ID_PAZIENTE A 176176 BTREE
paziente 1 IDX_DATA_NASCITA 1 DATA_NASCITA A 15594 YES BTREE
paziente 1 IDX_DATA_NASCITA 2 ID_SESSO A 25007 BTREE
paziente 1 IDX_DATA_NASCITA 3 ID_SPECIE A 17922 BTREE
paziente 1 IDX_COGNOME 1 COGNOME A 62479 YES BTREE
paziente 1 IDX_COGNOME 2 NOME A 163074 YES BTREE
paziente 1 IDX_COGNOME 3 ID_SESSO A 170270 BTREE
paziente 1 IDX_COGNOME 4 ID_SPECIE A 154908 BTREE
paziente 1 IDX_NOME 1 NOME A 55289 YES BTREE
paziente 1 IDX_NOME 2 COGNOME A 166062 YES BTREE
paziente 1 IDX_NOME 3 ID_SESSO A 176184 BTREE
paziente 1 IDX_NOME 4 ID_SPECIE A 176184 BTREE
paziente 1 FK_PAZIENTE_SPECIE 1 ID_SPECIE A 1 BTREE
paziente 1 FK_PAZIENTE_SESSO 1 ID_SESSO A 1 BTREE
如果我强制使用新的 IDX_NOME:
explain
select
specie5_.specie as col_5_0_,
paziente3_.cognome as col_8_0_
from
Analisi analisi0_
inner join
Paziente paziente3_ FORCE INDEX (IDX_NOME)
on analisi0_.ID_PAZIENTE=paziente3_.ID_PAZIENTE
inner join
Specie specie5_
on paziente3_.ID_SPECIE=specie5_.ID_SPECIE
where
paziente3_.nome like 'MARCO%'
;
结果如下:
id select_type table partitions type possible_keys key key_len ref rows filtered Extra
1 SIMPLE specie5_ index PRIMARY SPECIE 137 1 100 Using index
1 SIMPLE paziente3_ range IDX_NOME IDX_NOME 123 1350 100 Using where; Using index; Using join buffer (Block Nested Loop)
1 SIMPLE analisi0_ ref FK_ANALISI_PAZIENTE FK_ANALISI_PAZIENTE 4 gestelfolab.paziente3_.ID_PAZIENTE 1 100 Using index
也许我们可以说全表扫描 在这种情况下不是问题吗?
【问题讨论】:
-
从您以前的帖子中了解如何格式化帖子
-
a) 编辑您的问题,不要添加答案。 b)为所有相关表添加显示索引(物种似乎有问题)c)我建议使用索引
IDX_NOME (NOME, ID_SPECIE)(不是更多),反之亦然,但这似乎不是问题。 d) 您的统计数据看起来不错,但他们说每个ID_species在paziente中具有相同的值。那是对的吗? e) 由于某种原因,mysql 认为直接访问物种表太昂贵了。 f) 尝试: 1. 在like 'MARCO%';之后添加;。 2.尝试force index ...,如我的回答中所述。 3.ANALYZE TABLE paziente, species4.你的mysql是什么版本的? -
再次感谢您的宝贵时间,
-
再次感谢您的宝贵时间,我修改了我的第一个问题。索引更大,因为我正在寻找我的最终配置,并且我需要将近一晚来加载数据。在我的实际应用程序中,我可以搜索 COGNOME、NOME、ID_SESSO 和 ID_SPECIE,因为您描述的只是可以使用索引,所以我需要将它们全部放入索引中,对吗?是的,你是对的,在这个测试中,我在表 PAZIENTE 中只有一个 ID_SPECIE 的值,但我可以有大约 20 种不同的类型。 Mysql 是最新版本 5.7。我还添加了力指数结果
-
range表示 mysql 现在正在正确使用该索引(它不是全表扫描,这正是您所期望的)。您可以添加查询有无强制和第一个没有种类的查询所需的时间吗?我仍然不知道为什么必须强制使用mysql。您可以尝试使用结果较少的其他名称(然后没有强制)。您是否尝试过ANALYZE TABLES...(导入后)?尝试通过join Specie specie5_ ignore index (specie)禁止物种索引并对其进行测试。还有一句话:你不必重新导入数据来改变你的索引,使用create index ...和drop index ...!