2016-05-13 58 views
0

早上好, 我有兩個表,ANALISI有1462632個記錄,PAZIENTE有1408146個記錄,這個簡單的計數使用PAZIENTE的一個索引需要大概30秒的時間來回饋一下65000條記錄Mysql對兩個表之間的簡單查詢太慢

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上添加一個索引,但沒有好的結果。 有沒有提高性能的方法?

這是corrisponding解釋似乎確定我

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

在InnoDB中每個索引包含主鍵含蓄。

解釋計劃顯示在表Paziente上使用索引IDX_NOME。 DBMS在索引中查找名稱並在其中找到ID_PAZIENTE,這是我們需要訪問其他表的關鍵。所以沒有什麼補充。 (在另一個DBMS中,我們會在(NOME, ID_PAZIENTE)上添加一個複合索引,以便發生這種情況。)

然後有Analisi表要考慮。我們通過FK_ANALISI_PAZIENTE發現了一條記錄,其中包含用於查找匹配的ID_PAZIENTE,並且隱含地使用主鍵ID_ANALISI可以用來訪問表,但這甚至不是必需的,因爲我們從索引中獲得了所需的全部信息。我們在表格中找不到任何東西。 (再次,在另一個DBMS中,我們將在(ID_PAZIENTE, ID_ANALISI)上添加一個複合索引以覆蓋索引。)

因此,發生的僅僅是:讀取一個索引以讀取另一個索引以進行計數。完善。沒有什麼補充。

我們可以COUNT(*)取代COUNT(analisi0_.ID_ANALISI)因爲前者只說「數記錄,其中ID_ANALISI不爲空」,這始終是作爲ID_ANALISI是表的主鍵的情況。所以使用後者更簡單,並說「計數記錄」。但是,我不希望這會顯着加快查詢的速度。

所以從查詢的角度來看,沒有什麼可以加快速度。這裏有更多想到的東西:

  • 分區表?不,我看不到這方面的好處。查詢在並行線程中執行可能會更快,但據我所知,在MySQL中的多個分區上沒有並行執行。 (雖然我可能錯了)。
  • 對錶格進行碎片整理?不,表格本身在查詢中甚至沒有被訪問。
  • 這給我們留下了:購買更好的硬件。 (對不起,沒有給你更好的建議。)