0

我想在数据库中获取一些电子邮件,每封电子邮件都有一个状态。所有可能的状态都存储在一个表中,它们都具有权限(例如显示、编辑、删除等)。这些电子邮件不是通过网站获得权限的用户,而是用户添加的电子邮件列表。

这是表结构:

电子邮件表

    如果不存在 `email__email` 则创建表(
    `email_id` int(11) NOT NULL AUTO_INCREMENT,
    `created` 时间戳 NULL DEFAULT NULL,
    `updated` 时间戳 NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    `user_fk` int(11) 非空,
    `status_fk` tinyint(2) 非空,
    `language` enum('fr','en') 整理 utf8_unicode_ci DEFAULT NULL,
    `email` varchar(255) 整理 utf8_unicode_ci DEFAULT NULL,
    `firstName` varchar(255) 整理 utf8_unicode_ci DEFAULT NULL,
    `lastName` varchar(100) 整理 utf8_unicode_ci DEFAULT NULL,
    `companyName` varchar(255) 整理 utf8_unicode_ci DEFAULT NULL,
    `gender` enum('f','m') 整理 utf8_unicode_ci DEFAULT NULL,
    主键(`email_id`),
    唯一键 `user_email` (`user_fk`,`email`),
    KEY `user_fk` (`user_fk`),
    KEY `created` (`created`),
    KEY `status_fk` (`status_fk`)
    ) 引擎=InnoDB 默认字符集=utf8 排序=utf8_unicode_ci AUTO_INCREMENT=3031492 ;

状态表

    如果不存在 `email__status` 则创建表(
    `status_id` int(11) NOT NULL AUTO_INCREMENT,
    `name_fr` varchar(50) 整理 utf8_unicode_ci DEFAULT NULL,
    `name_en` varchar(50) 整理 utf8_unicode_ci DEFAULT NULL,
    `description_fr` varchar(150) 整理 utf8_unicode_ci DEFAULT NULL,
    `description_en` varchar(150) 整理 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',
    主键(`status_id`)
    ) 引擎=InnoDB 默认字符集=utf8 排序=utf8_unicode_ci AUTO_INCREMENT=7 ;

这是带有 EXPLAIN 的慢查询:

    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 组
    FROM `email__email` EE
    INNER JOIN email__status ES ON EE.status_fk = ES.status_id
    其中 1 = 1
    和 EE.user_fk = 54
    AND ES.permShow = 1
    ORDER BY EE.email_id DESC 限制 15


    EXTRA ID KEY KEY_LEN POSSIBLE_KEYS REF ROWS SELECT_TYPE TABLE TYPE
    使用临时的;使用文件排序 1 user_email 4 user_email,user_fk,status_fk const 180681 PRIMARY EE ref
    使用哪里;使用连接缓冲区 1 [空字符串] [空字符串] PRIMARY [空字符串] 6 PRIMARY ES ALL
    使用索引 2 email_fk 4 group_email,group_fk,email_fk mailing_dev.EE.email_id 1 DEPENDENT SUBQUERY GEC ref
    使用 where 2 PRIMARY 4 PRIMARY mailing_dev.GEC.group_fk 1 DEPENDENT SUBQUERY GC eq_ref

这是一个带有 EXPLAIN 的快速查询:

    选择 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 组
    FROM `email__email` EE
    其中 1 = 1
    和 EE.user_fk = 54
    AND EXISTS(从 email__status 中选择 permShow,其中 status_id = EE.status_fk AND permShow = 1)
    ORDER BY EE.email_id DESC 限制 15


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

两个查询之间存在很大差异,但第二个查询没有给我需要获取的两个重要列。我可以像 join 一样做子查询来获取它们,但我仍然不想每个都有很多子查询......有什么想法可以改进吗?

谢谢

4

1 回答 1

0

email__email.status_fk是一个 tinyint,但是email__status.status_id是一个 int(11)。

这可能会破坏您的 INNER JOIN。更改一种或另一种数据类型,然后重试。

于 2012-06-28T19:37:48.397 回答