2012-06-28 163 views
0

我想在數據庫中獲得一些電子郵件,並且每封電子郵件都有一個狀態。所有可能的狀態都存儲在一個他們都有權限的表格中(如顯示,編輯,刪除等)。這些電子郵件不是通過站點訪問權限的用戶,而是用戶添加的電子郵件列表。MySQL查詢優化 - 提高速度和效率

這裏是表結構:

電子郵件表

 
    CREATE TABLE IF NOT EXISTS `email__email` (
    `email_id` int(11) NOT NULL AUTO_INCREMENT, 
    `created` timestamp NULL DEFAULT NULL, 
    `updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    `user_fk` int(11) NOT NULL, 
    `status_fk` tinyint(2) NOT NULL, 
    `language` enum('fr','en') COLLATE utf8_unicode_ci DEFAULT NULL, 
    `email` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `firstName` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `lastName` varchar(100) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `companyName` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `gender` enum('f','m') COLLATE utf8_unicode_ci DEFAULT NULL, 
    PRIMARY KEY (`email_id`), 
    UNIQUE KEY `user_email` (`user_fk`,`email`), 
    KEY `user_fk` (`user_fk`), 
    KEY `created` (`created`), 
    KEY `status_fk` (`status_fk`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3031492 ; 

狀態表

 
    CREATE TABLE IF NOT EXISTS `email__status` (
    `status_id` int(11) NOT NULL AUTO_INCREMENT, 
    `name_fr` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `name_en` varchar(50) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `description_fr` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `description_en` varchar(150) COLLATE utf8_unicode_ci DEFAULT NULL, 
    `permShow` tinyint(1) NOT NULL DEFAULT '0', 
    `permSend` tinyint(1) NOT NULL DEFAULT '0', 
    `permEdit` tinyint(1) NOT NULL DEFAULT '0', 
    `permDelete` tinyint(1) NOT NULL DEFAULT '0', 
    `permImport` tinyint(1) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`status_id`) 
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=7 ; 

這裏與說明慢查詢:

 
    SELECT EE.*, ES.name_fr AS statusName, ES.description_fr AS statusDescription, ES.permShow, ES.permSend, ES.permEdit, ES.permDelete, ES.permImport 
    , (SELECT GROUP_CONCAT(CONVERT(CONCAT(GC.name, '~', GC.group_id), CHAR(255)) SEPARATOR ',') FROM `group` GC INNER JOIN group_email GEC ON GEC.group_fk = GC.group_id WHERE GEC.email_fk = EE.email_id AND GC.deleted = 0) AS groups 
    FROM `email__email` EE 
    INNER JOIN email__status ES ON EE.status_fk = ES.status_id 
    WHERE 1 = 1 
    AND EE.user_fk = 54 
    AND ES.permShow = 1 
    ORDER BY EE.email_id DESC LIMIT 15 


    EXTRA ID KEY KEY_LEN POSSIBLE_KEYS REF ROWS SELECT_TYPE TABLE TYPE 
    Using temporary; Using filesort 1 user_email 4 user_email,user_fk,status_fk const 180681 PRIMARY EE ref 
    Using where; Using join buffer 1 [empty string] [empty string] PRIMARY [empty string] 6 PRIMARY ES ALL 
    Using index 2 email_fk 4 group_email,group_fk,email_fk mailing_dev.EE.email_id 1 DEPENDENT SUBQUERY GEC ref 
    Using where 2 PRIMARY 4 PRIMARY mailing_dev.GEC.group_fk 1 DEPENDENT SUBQUERY GC eq_ref 

這裏是與解釋快速查詢:

 
    SELECT EE.* 
    , (SELECT GROUP_CONCAT(CONVERT(CONCAT(GC.name, '~', GC.group_id), CHAR(255)) SEPARATOR ',') FROM `group` GC INNER JOIN group_email GEC ON GEC.group_fk = GC.group_id WHERE GEC.email_fk = EE.email_id AND GC.deleted = 0) AS groups 
    FROM `email__email` EE 
    WHERE 1 = 1 
    AND EE.user_fk = 54 
    AND EXISTS(SELECT permShow FROM email__status WHERE status_id = EE.status_fk AND permShow = 1) 
    ORDER BY EE.email_id DESC LIMIT 15 


    EXTRA ID KEY KEY_LEN POSSIBLE_KEYS REF ROWS SELECT_TYPE TABLE TYPE 
    Using where 1 PRIMARY 4 user_email,user_fk [empty string] 270 PRIMARY EE index 
    Using where 3 PRIMARY 4 PRIMARY mailing_dev.EE.status_fk 1 DEPENDENT SUBQUERY email__status eq_ref 
    Using index 2 email_fk 4 group_email,group_fk,email_fk mailing_dev.EE.email_id 1 DEPENDENT SUBQUERY GEC ref 
    Using where 2 PRIMARY 4 PRIMARY mailing_dev.GEC.group_fk 1 DEPENDENT SUBQUERY GC eq_ref 

有兩個查詢,但第二個不給我,我需要獲取兩個重要的列之間有很大的區別。我可以做子查詢來獲取他們像一個連接會做但仍然,我不想有很多子查詢每個...任何想法來改善這一點?

由於

回答

0

email__email.status_fk是TINYINT,但email__status.status_id是一個int(11)。

這可能是污染你的INNER JOIN。更改一個或另一個數據類型,然後重試。

+0

將兩者都更改爲tinyint(2),然後更改爲int(11),但沒有更改...我運行優化查詢來檢查基數,但依然沒有任何變化。 EXPLAIN保留在Using臨時;在status_fk上使用filesort。儘管如此,我會繼續保持數據一致性的建議 – shallya