Mysql在两个表之间的简单查询上太慢了

时间:2016-05-13 08:10:24

标签: mysql

早上好, 我有两张桌子,ANALISI有1462632条记录,PAZIENTE有1408146条记录,这个简单计数使用PAZIENTE索引之一需要大约30秒才能回馈大约65000条记录

SELECT COUNT(analisi0_.ID_ANALISI) AS col_0_0_
FROM Analisi analisi0_
  INNER JOIN Paziente paziente1_ ON analisi0_.ID_PAZIENTE = paziente1_.ID_PAZIENTE
WHERE (paziente1_.nome LIKE 'MARIA%')

我也尝试在analisi0_.ID_PAZIENTE上添加一个索引,但效果不佳。 有没有办法提高性能?

这是对我来说似乎没问题的相应解释

Explain

CREATE TABLE ANALISI
(
   ID_ANALISI               INT             UNSIGNED NOT NULL AUTO_INCREMENT,
   ID_PAZIENTE              INT             UNSIGNED NOT NULL,
   ID_SESSIONE              INT             UNSIGNED NOT NULL,
   TRACCIATO                TINYINT         UNSIGNED NOT NULL,
   CAMPIONE                 VARCHAR(30),
   ID_PATOLOGICO            TINYINT         UNSIGNED,
   REPARTO                  VARCHAR(40),
   TOTALE_PROTEINE          FLOAT,   
   RAPP_AG                  FLOAT,
   ID_ANALISI_LINK          INT             UNSIGNED,
   ID_ANALISI_IFE           INT             UNSIGNED,   
   ID_ANALISI_DATI          INT             UNSIGNED,  
   ID_ANALISI_NOTA          INT             UNSIGNED,
   DATA_MODIFICA            DATETIME,      
   ID_UTENTE_MODIFICA       SMALLINT        UNSIGNED,
   DATA_VALIDAZIONE         DATETIME,
   ID_TIPO_VALIDAZIONE      TINYINT         UNSIGNED NOT NULL,
   ID_UTENTE_VALIDAZIONE    SMALLINT        UNSIGNED,   
   DATA_CANCELLAZIONE       DATETIME,
   ID_UTENTE_CANCELLAZIONE  SMALLINT        UNSIGNED,      
   PRIMARY KEY (ID_ANALISI), 
   INDEX IDX_CAMPIONE (CAMPIONE),
   INDEX IDX_REPARTO (REPARTO),   
   CONSTRAINT FK_ANALISI_PAZIENTE             FOREIGN KEY (ID_PAZIENTE)             REFERENCES PAZIENTE(ID_PAZIENTE),
   CONSTRAINT FK_ANALISI_SESSIONE             FOREIGN KEY (ID_SESSIONE)             REFERENCES SESSIONE(ID_SESSIONE),
   CONSTRAINT FK_ANALISI_PATOLOGICO           FOREIGN KEY (ID_PATOLOGICO)           REFERENCES PATOLOGICO(ID_PATOLOGICO),
   CONSTRAINT FK_ANALISI_TIPO_VALIDAZIONE     FOREIGN KEY (ID_TIPO_VALIDAZIONE)     REFERENCES TIPO_VALIDAZIONE(ID_TIPO_VALIDAZIONE),
   CONSTRAINT FK_ANALISI_UTENTE_MODIFICA      FOREIGN KEY (ID_UTENTE_MODIFICA)      REFERENCES UTENTE(ID_UTENTE), 
   CONSTRAINT FK_ANALISI_UTENTE_VALIDAZIONE   FOREIGN KEY (ID_UTENTE_VALIDAZIONE)   REFERENCES UTENTE(ID_UTENTE), 
   CONSTRAINT FK_ANALISI_UTENTE_CANCELLAZIONE FOREIGN KEY (ID_UTENTE_CANCELLAZIONE) REFERENCES UTENTE(ID_UTENTE),    
   CONSTRAINT FK_ANALISI_ANALISI_LINK         FOREIGN KEY (ID_ANALISI_LINK)         REFERENCES ANALISI(ID_ANALISI),
   CONSTRAINT FK_ANALISI_ANALISI_IFE          FOREIGN KEY (ID_ANALISI_IFE)          REFERENCES ANALISI_IFE(ID_ANALISI_IFE),
   CONSTRAINT FK_ANALISI_ANALISI_NOTA         FOREIGN KEY (ID_ANALISI_NOTA)         REFERENCES ANALISI_NOTA(ID_ANALISI_NOTA),
   CONSTRAINT FK_ANALISI_ANALISI_DATI         FOREIGN KEY (ID_ANALISI_DATI)         REFERENCES ANALISI_DATI(ID_ANALISI_DATI)
)
ENGINE=InnoDB;
CREATE TABLE PAZIENTE
(
   ID_PAZIENTE          INT           UNSIGNED NOT NULL AUTO_INCREMENT,
   ID_PAZIENTE_LAB      VARCHAR(20),
   COGNOME              VARCHAR(30),
   NOME                 VARCHAR(30),
   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),
   INDEX IDX_COGNOME (COGNOME),
   INDEX IDX_NOME (NOME),
   INDEX IDX_SESSO (ID_SESSO),
   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;

1 个答案:

答案 0 :(得分:1)

在InnoDB中,每个索引都隐式包含主键。

解释计划显示表IDX_NOME上使用了索引Paziente。 DBMS在索引中查找名称并在其中查找ID_PAZIENTE,这是我们访问另一个表所需的密钥。所以没有什么可补充的。 (在另一个DBMS中,我们会在(NOME, ID_PAZIENTE)上添加一个复合索引,以实现此目的。)

然后要考虑表Analisi。我们通过FK_ANALISI_PAZIENTE找到一条记录,其中包含用于查找匹配项的ID_PAZIENTE,以及可用于访问该表的主键ID_ANALISI,但这不是偶数必要的,因为我们从索引中获得了所需的所有信息。我们需要在表格中找到任何东西。 (同样,在另一个DBMS中,我们会在(ID_PAZIENTE, ID_ANALISI)上添加一个复合索引以获得覆盖索引。)

所以发生的事情仅仅是:读取一个索引以便读取另一个索引以便计数。完善。没有什么可补充的。

我们可以COUNT(analisi0_.ID_ANALISI)替换COUNT(*),因为前者只说"计算ID_ANALISI不为空的记录",这是始终是ID_ANALISI是表格的主键。因此,使用后者更简单,并说“记录记录”#34;。但是,如果有的话,我不希望这会大大加快查询速度。

因此从查询的角度来看,没有什么可以加快速度。以下是我想到的更多事情:

  • 分区表?不,我认为这没有任何好处。然后在并行线程中执行查询可能会更快,但据我所知,MySQL中的多个分区上没有并行执行。 (虽然我可能错了。)
  • 对表进行碎片整理?不,甚至在查询中都没有访问表本身。
  • 这让我们有了:购买更好的硬件。 (抱歉没有更好的建议。)