使用join或sequential更快哪个更新?

时间:2012-11-22 19:19:51

标签: mysql query-optimization mysql-5.0

这个问题按照我的previous Question所需更新顺序删除一行。

我可以使用存储过程而不是触发器或嵌套查询来编写两个解决方案。

两者都使用辅助函数my_signal(msg)

Employee表中删除员工的存储过程。

  • 拳头解决方案:在表格中使用UPDATE行,不加入联接操作
CREATE PROCEDURE delete_employee(IN dssn varchar(64))
BEGIN
    DECLARE empDesignation varchar(128);
    DECLARE empSsn         varchar(64);
    DECLARE empMssn        varchar(64);
     SELECT SSN, designation, MSSN  INTO empSsn, empDesignation, empMssn 
     FROM Employee 
     WHERE SSN = dssn;

   IF (empSsn IS NOT NULL) THEN
    CASE       
           WHEN empDesignation = 'OWNER' THEN 
               CALL my_signal('Error: OWNER can not deleted!');

           WHEN empDesignation = 'WORKER' THEN 
            DELETE FROM Employee WHERE SSN = empSsn;               

           WHEN empDesignation = 'BOSS' THEN 
               BEGIN 
                   UPDATE Employee
                   SET MSSN = empMssn
                   WHERE MSSN = empSsn;

                DELETE FROM Employee WHERE SSN = empSsn;                   

               END;
    END CASE;
   ELSE 
               CALL my_signal('Error: Not a valid row!');
   END IF;
END//  
  • 第二个解决方案:正如我在上一个问题中使用INNER JOIN
  • 建议的那样
CREATE PROCEDURE delete_employee(IN dssn varchar(64))
BEGIN
    DECLARE empDesignation varchar(128);
    DECLARE empSsn         varchar(64);
    DECLARE empMssn        varchar(64);
      SELECT SSN, designation, MSSN  INTO empSsn, empDesignation, empMssn 
      FROM Employee 
      WHERE SSN = dssn;

   IF (empSsn IS NOT NULL) THEN
       IF (empDesignation = 'OWNER') THEN 
        CALL my_signal('Error: OWNER can not deleted!');
       END IF;

       UPDATE `Employee` A INNER JOIN `Employee` B ON A.SSN= B.MSSN
       SET B.MSSN = A.MSSN WHERE A.SSN = empSsn;

       DELETE FROM `Employee` WHERE SSN = empSsn;
   ELSE 
       CALL my_signal('Error: Not a valid row!');
   END IF;    
END//

我读到here使用连接对Efficient SELECT有效。但我的问题只包括一个表,我觉得我的解决方案(第一个)比第二个效率高,因为连接会比较消耗内存。

如果Employee table足够大,请建议我哪个更好,更有效率。 哪个更适合我?原因

编辑:我检查过只有7行的小表,两个解决方案都需要同时进行。

mysql> CALL delete_employee(4);
Query OK, 1 row affected (0.09 sec)

我知道SQL函数的行为是非确定性的,因为表启发式。哪个选择更好?如果你有一些想法如何进一步优化查询。

1 个答案:

答案 0 :(得分:0)

经过一段时间的思考,我几乎可以肯定它没有什么区别,第一个解决方案可能会稍微慢一些,但是在一个不可测量的维度上。

第一个意图是,第一个解决方案更快,因为你首先通过id获取数据,并且仅在nessesary时更新。

但MySQL内部在UPDATE .. JOIN语句中没有做任何其他事情,只是在内部,因此也可能更有效。

您的第一个解决方案没有发现默认情况 - 如果我既没有WORKERBOSS又会怎样?

此外,您的执行时间(0.09秒)非常高,目前为止无法用我对您的数据库进行解释。

您是否设置了任何索引?

修改

查看table structure you've posted here后 我对结构本身有一些改进。

1。在存储int时使用类型integer values。数据库可以更有效地处理整数方式

2。为什么要自己生成SSN?在auto_increment上使用PRIMARY KEY可以更轻松地处理并在您添加新员工时为您节省大量工作

ALTER TABLE `Employee`
    CHANGE `SSN` `SSN` int(11) NOT NULL AUTO_INCREMENT ,
    CHANGE `MSSN` `MSSN` int(11) DEFAULT NULL,
    ADD KEY `KEY_Employee_MSSN` ( `MSSN` );

3。您是否使用该名称进行查找?如果是这样,它也必须是唯一的

ALTER TABLE `Employee`
    ADD UNIQUE KEY `UNI_KEY_Employee` ( `name` );

4. 你有固定的指定范围吗?枚举强制输入为定义值之一

ALTER TABLE `Employee`
    CHANGE `designation` `designation` ENUM( 'BOSS', 'WORKER' ) NOT NULL DEFAULT 'WORKER',
    ADD KEY `KEY_Employee_designation` ( `designation` );

最终结构

mysql> EXPLAIN `Employee`;

+-------------+-----------------------+------+-----+---------+----------------+
| Field       | Type                  | Null | Key | Default | Extra          |
+-------------+-----------------------+------+-----+---------+----------------+
| SSN         | int(11)               | NO   | PRI | NULL    | auto_increment |
| name        | varchar(64)           | YES  | UNI | NULL    |                |
| designation | enum('BOSS','WORKER') | NO   | MUL | WORKER  |                |
| MSSN        | int(11)               | YES  | MUL | NULL    |                |
+-------------+-----------------------+------+-----+---------+----------------+
4 rows in set (0.00 sec)