Mysql是否比在字符串中使用where子句中的数字更快?

时间:2010-08-28 07:48:19

标签: sql mysql query-optimization

假设您有4种类型的评估,测试,测验,MiniQuiz和FinalExam

我们将记录存储在数据库中,如此

studentid ----- assesType
1                test
2                quiz
3                quiz
4                quiz
5                miniquiz
6                miniquiz
7                final
8                final

它更快,为每种类型分配数字的更好方法可以说:

test = 1 测验= 2 miniquiz = 3 final = 4

并使用此代替记录保存。

studentid ----- assesType
1                1
2                2
3                2
4                2
5                3
6                3
7                4
8                5

我真的想问,这样做是否值得?优势等?因为在执行此操作时,用服务器端语言编写代码变得有点困难。

谢谢=)

3 个答案:

答案 0 :(得分:2)

是的,使用数字效率更高,这是标准惯例。

SQL和关系数据库是为这种存储而构建的。

例如:

select students.studentid, assessments.assesName AS assesType
from students
  inner join assessments on (students.assesType = assesments.assesType)

答案 1 :(得分:2)

是的,数字比较比字符串比较更快。字符串也占用更多空间,数据重复意味着如果您必须将“miniquiz”重命名为“microquiz”,则必须更新所有行。最后,也许最重要的是,您的数据库将无法拒绝不可接受的字符串:您说有四种类型的评估,但您的数据库将很乐意接受您传递的任何字符串。

通常,您可能希望创建另一个表,可能只使用assesTypesid字段调用它name,并保留所有可接受的类型。然后在主表中,将assesType字段设为foreign key,引用新id表的assesTypes属性。例如:

CREATE TABLE assesTypes (
   id    int,
   name  varchar(15),
   PRIMARY KEY (id)
) ENGINE=INNODB;

CREATE TABLE assessments (
   student_id    int,
   assesType     int,
   mark          int,
   PRIMARY KEY (student_id, assesType),
   FOREIGN KEY (assesType) REFERENCES assesTypes (id)
) ENGINE=INNODB;

现在我们可以填充assesTypes表:

INSERT INTO assesTypes VALUES (1, 'Test');
INSERT INTO assesTypes VALUES (2, 'Quiz');
INSERT INTO assesTypes VALUES (3, 'MiniQuiz');
INSERT INTO assesTypes VALUES (4, 'FinalExam');

现在让我们将一些评估数据插入assessments表:

INSERT INTO assessments VALUES (1, 1, 55);
INSERT INTO assessments VALUES (1, 2, 65);
INSERT INTO assessments VALUES (1, 3, 75);

这一切都很好。我们现在可INNER JOIN assessments表与assessTypes表格如下:

SELECT a.student_id, at.name, a.mark
FROM   assessments a
JOIN   assesTypes at ON (at.id = a.assesType);

对于这个结果:

+------------+----------+------+
| student_id | name     | mark |
+------------+----------+------+
|          1 | Test     |   55 |
|          1 | Quiz     |   65 |
|          1 | MiniQuiz |   75 |
+------------+----------+------+
3 rows in set (0.00 sec)

现在让我们尝试在assesType表格中插入无效的assessments

INSERT INTO assessments VALUES (1, 5, 75);

我们做不到。 MySQL将报告:

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails

外键不需要具有可用的关系数据库,但它们对于避免破坏关系和孤立行(即referential integrity)至关重要。 ACID中的C需要能够在数据库级别强制实施参照完整性。

答案 2 :(得分:0)

您应该使用第二种方法。但主要优点不是性能,而是数据的可维护性。

通过将assesType存储在一个单独的表中并按ID引用该表,您可以确保不会为不同的assesTypes获得不同的拼写,您可以轻松地重命名assesType而无需更新整个数据库。您还可以获得保持assesTypes的单独维护的好处,在将学生分配给assesType时,您不会意外地创建新的assesType。在GUI中为可用的assesTypes创建列表时,您还可以快速地询问您具有哪种类型的assesTypes。

您可以查看database normalization,了解有关如何构建数据的更多“规则”。