获取mysql结果的最佳方法

时间:2015-07-07 19:17:41

标签: mysql sql stored-procedures view triggers

我真的可以帮助我参加暑期实习的项目。我需要知道是否有更好/更简单的方法。我有9个表,其中包含我需要整合到1个表中的信息。该项目旨在帮助基于cl_no和c_no限制基于特定用户的访问。我们只想要基于表的不同c_no cl_no。我首先编写了以下脚本作为视图,以查看我将要使用的所有相关记录。

   SELECT DISTINCT
        `contacts_callmeet`.`c_no` AS `c_no`,
        `contacts_callmeet`.`ccm_cl_no` AS `ccm_cl_no`,
        1 AS `ti_no`,
        1 AS `ctc_status`,
        `contacts_callmeet`.`a_no` AS `a_no`
    FROM
        `contacts_callmeet`
    WHERE
        ((`contacts_callmeet`.`ccm_status` = 1)
            AND (`contacts_callmeet`.`ccm_cl_no` IS NOT NULL)
            AND (`contacts_callmeet`.`ccm_cl_no` <> 0))

    UNION SELECT DISTINCT
        `contacts_notes`.`c_no` AS `c_no`,
        `contacts_notes`.`cl_no` AS `cl_no`,
        2 AS `ti_no`,
        1 AS `ctc_status`,
        `contacts_notes`.`a_no` AS `a_no`
    FROM
        `contacts_notes`
    WHERE
        ((`contacts_notes`.`cn_status` = 1)
            AND (`contacts_notes`.`cl_no` IS NOT NULL)
            AND (`contacts_notes`.`cl_no` <> 0)
            AND (`contacts_notes`.`c_no` IS NOT NULL))

    UNION SELECT DISTINCT
        `d`.`c_no` AS `c_no`,
        `d`.`cl_no` AS `cl_no`,
        3 AS `ti_no`,
        1 AS `ctc_status`,
        `d`.`a_no` AS `a_no`
    FROM
        `disbursements` `d`
    WHERE
        ((`d`.`disb_status` = 1)
            AND (`d`.`cl_no` IS NOT NULL)
            AND (`d`.`cl_no` <> 0)
            AND (`d`.`c_no` IS NOT NULL))

    UNION SELECT DISTINCT
        `ea`.`c_no` AS `c_no`,
        `e`.`cl_no` AS `cl_no`,
        4 AS `ti_no`,
        1 AS `ctc_status`,
        `e`.`a_no` AS `a_no`
    FROM
        (`events_attendees` `ea`
        JOIN `events` `e` ON ((`e`.`e_no` = `ea`.`e_no`)))
    WHERE
        ((`ea`.`ea_status` = 1)
            AND (`e`.`e_status` = 1)
            AND (`e`.`cl_no` IS NOT NULL)
            AND (`e`.`cl_no` <> 0)
            AND (`ea`.`c_no` IS NOT NULL))

    UNION SELECT DISTINCT
        `gj`.`c_no` AS `c_no`,
        `g`.`cl_no` AS `cl_no`,
        5 AS `ti_no`,
        1 AS `ctc_status`,
        `g`.`a_no` AS `a_no`
    FROM
        (`groups` `g`
        JOIN `groups_join` `gj` ON ((`g`.`g_no` = `gj`.`g_no`)))
    WHERE
        ((`g`.`g_status` = 1)
            AND (`g`.`cl_no` IS NOT NULL)
            AND (`g`.`cl_no` <> 0)
            AND (`gj`.`c_no` IS NOT NULL))

    UNION SELECT DISTINCT
        `pledges`.`c_no` AS `c_no`,
        `pledges`.`cl_no` AS `cl_no`,
        6 AS `ti_no`,
        1 AS `ctc_status`,
        `pledges`.`a_no` AS `a_no`
    FROM
        `pledges`
    WHERE
        ((`pledges`.`pl_status` = 1)
            AND (`pledges`.`cl_no` IS NOT NULL)
            AND (`pledges`.`cl_no` <> 0)
            AND (`pledges`.`c_no` IS NOT NULL))

    UNION SELECT DISTINCT
        `ec`.`c_no` AS `c_no`,
        `e`.`cl_no` AS `cl_no`,
        7 AS `ti_no`,
        1 AS `ctc_status`,
        `e`.`a_no` AS `a_no`
    FROM
        (`events_cohosts` `ec`
        JOIN `events` `e` ON ((`e`.`e_no` = `ec`.`e_no`)))
    WHERE
        ((`ec`.`ec_status` = 1)
            AND (`e`.`e_status` = 1)
            AND (`e`.`cl_no` IS NOT NULL)
            AND (`e`.`cl_no` <> 0)
            AND (`ec`.`c_no` IS NOT NULL))

    UNION SELECT DISTINCT
        `cl`.`c_no` AS `c_no`,
        `clp`.`cl_no` AS `cl_no`,
        8 AS `ti_no`,
        1 AS `ctc_status`,
        `cl`.`a_no` AS `a_no`
    FROM
        (`comm_list` `cl`
        JOIN `comm_list_parent` `clp` ON ((`clp`.`clp_no` = `cl`.`clp_no`)))
    WHERE
        ((`clp`.`clp_status` = 1)
            AND (ISNULL(`cl`.`coml_status`)
            OR (`cl`.`coml_status` = 1))
            AND (`clp`.`cl_no` IS NOT NULL)
            AND (`clp`.`cl_no` <> 0)
            AND (`cl`.`c_no` IS NOT NULL))

    UNION SELECT DISTINCT
        `commitments`.`c_no` AS `c_no`,
        `commitments`.`cl_no` AS `cl_no`,
        9 AS `ti_no`,
        1 AS `ctc_status`,
        `commitments`.`a_no` AS `a_no`
    FROM
        `commitments`
    WHERE
        ((`commitments`.`commit_status` = 1)
            AND (`commitments`.`cl_no` IS NOT NULL)
            AND (`commitments`.`cl_no` <> 0)
            AND (`commitments`.`c_no` IS NOT NULL))

然后我意识到运行时间很长(50多秒),所以我开始为每个表编写触发器来填充一个名为contacts_table_clients的表(见下文)。一个表的触发器可以在下面看到。

ctc_no,c_no,cl_no,ti_no,ctc_status,a_no

88,6972179,2000,2,1,151

CREATE DEFINER=`IDPAdmin`@`%` TRIGGER `IDP1`.`contacts_notes_AFTER_INSERT` AFTER INSERT ON `contacts_notes` FOR EACH ROW
BEGIN
DECLARE records int(10);


IF new.cl_no is not null
THEN

select count(c_no) into records from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in 
(select cl_no from contacts_table_clients where ctc_status = 1 and c_no = new.c_no and ti_no = 2);

END IF;

IF records > 0
 THEN 
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF; 


CREATE DEFINER=`IDPAdmin`@`%` TRIGGER `IDP1`.`contacts_notes_AFTER_UPDATE` AFTER UPDATE ON `contacts_notes` FOR EACH ROW
BEGIN
DECLARE old_cl_no int(10);
DECLARE new_cl_no int(10);
DECLARE delete_c_no int(10);
DECLARE delete_cl_no int(10);
DECLARE records int(10);
DECLARE records_2 int(10);
DECLARE old_cl_no_select int(10);
DECLARE new_cl_no_select int(10);

IF new.cl_no > 0 and old.cl_no is null
 THEN 

 DROP TEMPORARY TABLE IF EXISTS tmp_contacts_notes_2;
create temporary table tmp_contacts_notes_2
select c_no, cl_no,a_no from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in 
(select cl_no from contacts_table_clients where ctc_status = 1 and ti_no = 2 and c_no = new.c_no);


select count(*) into records_2 from tmp_contacts_notes_2;
 END IF;


 IF records_2 > 0
 THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;


IF new.cn_status = 0 or new.cl_no is null


THEN
select distinct c_no into delete_c_no
from contacts_table_clients 
where ctc_status = 1
                and ti_no = 2
and c_no = new.c_no 
and cl_no not in (select cl_no 
from contacts_notes 
                                    where c_no = new.c_no 
                                    and cn_status = 1
                                    and cl_no is not null);

select distinct cl_no into delete_cl_no
from contacts_table_clients 
where ctc_status = 1
                and ti_no = 2
and c_no = new.c_no 
and cl_no not in (select cl_no 
from contacts_notes 
                                    where c_no = new.c_no 
                                    and cn_status = 1
                                    and cl_no is not null);

    UPDATE contacts_table_clients 
    set ctc_status = 0 
    where ti_no = 2 
    and c_no = delete_c_no 
    and cl_no = delete_cl_no;

END IF;


IF new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0
THEN


select cl_no into old_cl_no
from contacts_table_clients 
where ti_no = 2 
        and ctc_status = 1
        and c_no = new.c_no
        and cl_no not in (select cl_no 
from contacts_notes 
                            where c_no = new.c_no 
                            and cn_status = 1 
                            and cl_no is not null);





select cl_no into new_cl_no
from contacts_notes 
where c_no = new.c_no 
and cn_status = 1 
and cl_no not in (select cl_no 
from contacts_table_clients 
                        where ti_no = 2 
and c_no = new.c_no
and ctc_status = 1
                            and cl_no is not null);


END IF;

IF new_cl_no > 0 and old_cl_no > 0
THEN

UPDATE contacts_table_clients set cl_no = new_cl_no where ctc_status = 1 and ti_no = 1 and c_no = new.c_no and cl_no = old_cl_no;

END IF;


IF  new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0


THEN

select distinct cl_no into delete_cl_no
from contacts_table_clients 
where ctc_status = 1
                and ti_no = 2
and c_no = new.c_no 
and cl_no not in (select cl_no 
from contacts_notes 
                                    where c_no = new.c_no 
                                    and cn_status = 1
                                    and cl_no is not null);

    UPDATE contacts_table_clients 
    set ctc_status = 0 
    where ti_no = 2 
    and c_no = new.c_no 
    and cl_no = delete_cl_no;

END IF;

















IF delete_cl_no < 0 and (old_cl_no is null or new_cl_no is null or new_cl_no < 1 or old_cl_no < 1)
THEN
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);

END IF;


IF new.cl_no <> old.cl_no and old_cl_no > 0 and new.cl_no is not null
THEN
DROP TEMPORARY TABLE IF EXISTS tmp_contacts_notes;
create temporary table tmp_contacts_notes
select c_no, cl_no,a_no from contacts_notes where cn_status = 1 and c_no = new.c_no and cl_no is not null and cl_no not in 
(select cl_no from contacts_table_clients where ctc_status = 1 and ti_no = 2 and c_no = new.c_no);


select count(*) into records from tmp_contacts_notes;

END IF;

IF records > 0
 THEN 
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`
)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;





IF new.cl_no <> old.cl_no and new.cl_no is not null and new.cl_no <> 0
THEN
select count(cl_no) into old_cl_no_select
from contacts_notes 
                            where c_no = new.c_no 
                            and cn_status = 1 
                            and cl_no is not null
                            and cl_no not in (select cl_no 
from contacts_table_clients 
where ti_no = 2 
        and ctc_status = 1
        and c_no = new.c_no);

END IF;

IF old_cl_no_select > 0
 THEN 
INSERT INTO `IDP1`.`contacts_table_clients`
(`c_no`,
`cl_no`,
`ti_no`,
`a_no`)
VALUES
(new.c_no,
new.cl_no,
2,
new.a_no);
END IF;



END

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

工会没问题。

首先分离SQL语句,然后观察每个语句需要多长时间。

我猜他们中的一两个人会查询一张非常大的桌子。做一个Explain来找出需要这么长时间的事情。可能缺少一些索引。

像这样添加:

ALTER TABLE `contacts_callmeet` ADD INDEX `ccm_status` (`ccm_status`)

我最近遇到了一个问题并以类似的方式解决了这个问题。似乎MySQL处理一个单独的表,索引比使用连接和/或联合更好。

方法很好(我在第一次查询时性能提升了大约1500倍),正如Thorsten所说:想想你是否想要在工会之前区别开来。也许你想要那个,我想当你最后做一个截然不同的结果会更快。