数据库实验一:数据定义与操作语言实验

news2024/11/17 3:54:11

实验一 数据定义与操作语言实验

实验 1.1 数据库定义实验

1.实验目的

理解和掌握数据库DDL语言,能够熟练地使用SQL DDL语句创建、修改和删除数据库、模式和基本表。

2.实验内容和要求

理解和掌握SQL DDL语句的语法,特别是各种参数的具体含义和使用方法;使用SQL语句创建、删除和修改数据库、模式和基本表。掌握SQL常见语法错误的调试方法。

3.实验重点和难点

实验重点:创建数据库、基本表。 ​ 实验难点:创建基本表时,为不同的列选择合适的数据类型,正确创建表级和列级完整性约束,如列值是否允许为空、主码和外码等。注意:数据完整性约束可以在创建基本表时定义,也可以先创建表然后定义完整性约束。由于完整性约束的限制,被引用的表要先创建。

4.实验过程

本实验建立AAS数据库模式。AAS数据库模式由学生表(student),课程表(course),选课表(sc)三个基本表组成。后续的实验也使用该数据库,但根据不同的实验设计添加了其他的基本表。

(1)定义模式

在数据库中创建名为AAS的模式。并切换到该模式。

CREATE SCHEMA AAS;
USE AAS;

(3)定义基本表

在数据库的AAS模式中建立基本表。

CREATE TABLE student(   /*学生信息表*/
    Sno CHAR(9),
    Sname CHAR(20),
    Ssex CHAR(2),
    Sage SMALLINT,
    Sdept CHAR(20)
    );
CREATE TABLE Course(    /*课程信息表*/
    Cno CHAR(9),
    Cname CHAR(20),
    Cpno CHAR(9),
    Ctype CHAR(5),
    Cdept CHAR(20),
    Chours SMALLINT,
    Ccredit SMALLINT
    );  
CREATE TABLE SC(        /*选课信息表*/
    Sno CHAR(9),
    Cno CHAR(4),
    Grade SMALLINT
    );  

5.实验总结

使用CREATE语句定义三个基本表,实体完整性和参照完整性在后续实验中进行定义。

6.思考题

(1)SQL语法规定,双引号括定的符号串为对象名称,单引号括定的符号串为常量字符串,那么什么情况下需要用双引号来界定对象名?

MYSQL中,双引号和单引号都用于表示常量字符串。反引号用于区分保留字和与保留字同名的对象。

(2)数据库对象的完整引用是"服务器名.数据库名.模式名.对象名",但通常可以省略服务器名和数据库名,甚至模式名,直接用对象名访问对象即可。清设计相应的实验验证基本表及列的访问方法。

MYSQL中不区分数据库名和模式名。如果直接访问对象,需要以模式名.表名访问表,如果表名已经出现了,列名就可以直接使用。

SELECT sno FROM aas.SC;

MYSQL中可以使用USE命令选择数据库或模式,选择后可以直接使用对象名访问对象,不需要添加模式名或数据库名。

USE aas;
SELECT sno FROM SC;

实验 1.2 数据基本查询实验

1.实验目的

掌握 SQL 程序设计基本规范,熟练运用 SQL 语言实现数据基本查询,包括单表查询、分组统计查询和连接查询。

2.实验内容和要求

针对数据库设计各种单表查询 SQL 语句、分组统计查询语句;设计单个表针对自身的连接查询,设计多个表的连接查询。理解和掌握 SQL 查询语句各个字句的特点和作用,按照 SQL 程序设计规范写出具体的 SQL 查询语句,并调试通过。

3.实验重点和难点

实验重点:分组统计查询、单表自身连接查询、多表连接查询。 ​ 实验难点:区分元组过滤条件和分组过滤条件;确定连接属性,正确设计连接条件。

4.实验过程

(1)单表查询(实现投影操作)

查询学生的姓名,性别和年龄。

SELECT Sname,Ssex,Sage
FROM student;

(2)单表查询(实现选择操作)

查询信息科学与工程学院所有男生的所有信息。

SELECT *
FROM student
WHERE sdept="CS" AND ssex="男";

(3)不带分组过滤条件的分组统计查询

查询每个学生的课程门数。

SELECT s.sno,COUNT(cno) "课程数"
FROM student s,sc
WHERE sc.sno=s.sno
GROUP BY s.sno;

(4)带分组过滤条件的分组统计查询

查询课程数大于等于4的学生学号和姓名。

SELECT s.sno,MAX(sname),COUNT(cno) 课程数
FROM student s,sc
WHERE sc.sno=s.sno
GROUP BY s.sno
HAVING 课程数>=4;

(5)单表自身连接查询

查询与学号为202012210的学生修读相同课程的学生学号。

SELECT sc2.sno
FROM sc sc1,sc sc2
WHERE sc1.sno="202012210" AND sc1.cno = sc2.cno;

(6)两表连接查询

查询选修了课程号为5的学生的学生信息。

SELECT *
FROM student,sc
WHERE sc.cno='5' AND sc.sno=student.sno;
/*结果中含有重复的属性列sno,连接时去掉重复的属性列,使用下面的自然连接*/

(7)两表连接查询(自然连接)

查询选修了课程号为5的学生的学生信息。

SELECT *
FROM student
NATURAL JOIN sc
WHERE sc.cno='5';

(8)三表连接查询

查询"姜和光"修读的所有课程的课程编号,课程名,课程学时,课程学分。

SELECT c.cno,c.cname,c.chours,c.ccredit
FROM student s,course c,sc
where s.sname="姜和光" AND s.sno=sc.sno AND sc.cno=c.cno; 

5.实验总结

正确查询需要对数据库模式和各个表的结构充分理解。查询中常用的分组,连接查询需要熟练掌握。需要注意GROUP BY子句使用时,SELECT的属性必须都在GROUP子句中。

6.思考题

(1)不在GROUP BY子句出现的属性,是否可以出现在SELECT子句中?请举例并验证。

不可以,例如以下查询语句是不可以执行的。

SELECT cno,COUNT(*) FROM sc GROUP BY sno;

(2)请举例说明分组统计查询中的WHERE和HAVING有何区别?

WHERE是在产生结果之前约束查询到的数据的,且不能使用聚集函数。而HAVING在查询返回结果集以后过滤结果,并可以使用聚合函数。例如以下的语句,只能使用HAVING而不能使用WHERE:

SELECT AVG(grade) FROM SC GROUP BY sno
HAVING AVG(grade) > 80;

(3)连接查询速度是影响关系数据库性能的关键因素,请讨论如何提高连接查询速度。

使用WHERE添加条件,减少需要连接的数据量。充分利用连接条件,当两个表有不止一个连接条件时,全部添加到WHERE子句当中。尽量使用数字型字段,因为连接时数字型字段的比较比字符型更快。

实验 1.3 数据高级查询实验

1.实验目的

掌握SQL嵌套查询和集合查询等各种高级查询的设计方法等。

2.实验内容和要求

针对数据库正确分析用户查询要求,设计各种嵌套查询和集合查询。

3.实验重点和难点

实验重点:嵌套查询。

实验难点:相关子查询、多层EXIST嵌套查询。

4.实验过程

(1)IN嵌套查询

查询选择了信息科学与工程学院开设的课程的学生。

SELECT Sno,Sname
FROM Student
WHERE Sno IN (
    SELECT Sno
    FROM SC,Course C
    WHERE SC.Cno=C.Cno AND C.Cdept="信息科学与工程学院"
);

(2)带有比较运算符的子查询

查询每个学生大于等于他自己选修课程平均成绩的课程号。

SELECT Sno,Cno
FROM SC
WHERE GRADE>=(
	SELECT AVG(GRADE)
    FROM SC SC1
    WHERE SC.Sno=SC1.Sno
);

(3)带有ANY或ALL的子查询

查询非计算机科学系比计算机科学系中任意一个学生年龄小的学生姓名和年龄。

SELECT Sname,Sage
FROM Student 
WHERE Sdept!="CS" AND Sage<ANY(
	SELECT Sage
    FROM Student
    WHERE Sdept="CS"
);

查询非计算机科学系比计算机科学系中所有学生年龄都小的学生姓名和年龄。

SELECT Sname,Sage
FROM Student 
WHERE Sdept!="CS" AND Sage<ALL(
	SELECT Sage
    FROM Student
    WHERE Sdept="CS"
);

(4)单层EXISTS嵌套查询

查询没有修读算法设计与分析课程的计科专业的学生。

SELECT Sno,Sname
FROM Student
WHERE NOT EXISTS (
	SELECT SC.Sno
    FROM SC,Course
    WHERE SC.Cno=Course.Cno AND Course.Cname="算法设计与分析"
    	AND Student.Sno=SC.Sno
) AND Sdept="CS";

(5)双层EXISTS嵌套查询

查询修读了所有"刘晨"修读的课程的学生。

/*查找一个学生,不存在刘晨修读而他没有修读的课程*/
SELECT Sno,Sname
FROM Student S
WHERE NOT EXISTS (
	SELECT *			/*刘晨修读而他没有修读的课程*/
	FROM SC,Student S1	/*从SC中找出了所有刘晨修读的课程*/
	WHERE SC.Sno=S1.Sno AND S1.Sname="刘晨" AND NOT EXISTS(
		SELECT *
		FROM SC SC1
		WHERE SC1.Cno=SC.Cno AND SC1.Sno=S.Sno	
    )
);

(6)FROM子句中的嵌套查询(基于派生表的查询)

查询修读课程平均成绩超过80的计科专业的学生。

SELECT S.*
FROM Student S,(					 /*子查询生成的临时派生表为T表*/
	SELECT Sno,AVG(GRADE) avg_grade
	FROM SC 
	GROUP BY SC.Sno
	) T
WHERE S.Sno = T.Sno AND S.Sdept='CS' AND T.avg_grade>80;

(7)集合查询(交)

查询"刘晨"和"李勇"都修读过的课程的信息。使用的MYSQL不支持INTERSECT语句,以下是SQL语句的方式。

SELECT C.* 
FROM Student S,SC,Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno AND S.Sname="刘晨"
INTERSECT
SELECT C.* 
FROM Student S,SC,Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno AND S.Sname="李勇";

使用嵌套查询替代INTERSECT语句进行以上查询如下:

SELECT C.* 
FROM Student S,SC,Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno AND S.Sname="刘晨" AND C.Cno IN(
    SELECT C1.Cno
	FROM Student S1,SC SC1,Course C1
	WHERE S1.Sno=SC1.Sno AND SC1.Cno=C1.Cno AND S1.Sname="李勇"
);

(8)集合查询(并)

查询"刘晨"和"李勇"修读过的课程的信息

SELECT C.* 
FROM Student S,SC,Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno AND S.Sname="刘晨"
UNION
SELECT C.* 
FROM Student S,SC,Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno AND S.Sname="李勇";

(9)集合查询(差)

查询"刘晨"修读过而"李勇"没有修读过的课程信息。MYSQL不支持EXCEPT语句,SQL语句使用EXCEPT进行查询的方式如下:

SELECT C.* 
FROM Student S,SC,Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno AND S.Sname="刘晨"
EXCEPT
SELECT C.* 
FROM Student S,SC,Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno AND S.Sname="李勇";

使用嵌套查询替代EXCEPT语句进行查询如下:

SELECT C.* 
FROM Student S,SC,Course C
WHERE S.Sno=SC.Sno AND SC.Cno=C.Cno AND S.Sname="刘晨" AND C.Cno NOT IN(
    SELECT C1.Cno
	FROM Student S1,SC SC1,Course C1
	WHERE S1.Sno=SC1.Sno AND SC1.Cno=C1.Cno AND S1.Sname="李勇"
);

5.实验总结

SQL中没有全称量词和蕴含,可以通过等价转换,使用EXISTS和NOT EXISTS语句实现。集合查询的交INTERSECT和差EXCEPT在MYSQL中没有语句,可以使用嵌套查询的方式实现。

6.思考题

(1)试分析什么类型的查询可以用连接查询实现,什么只能用嵌套查询实现。

当所查询的内容在多个表中时,需要通过连接查询实现,而当所查询的内容在一个表中,而查询的条件需要对其他表的数据进行统计时,就只能使用嵌套查询。

(2)试分析不相关子查询和相关子查询的的区别。

不相关子查询中,子查询的查询条件不依赖于父查询,查询的一种方法是先执行子查询,子查询的结果用于父查询的条件。而相关子查询中,子查询的查询条件依赖于父查询,查询中需要先从外层查询取出一个元组,执行内层查询,再执行外层查询,然后从外层查询中取出下个元组重复上述过程。

实验 1.4 数据更新实验

1.实验目的

熟悉数据库的数据更新操作,能够使用户SQL语句对数据库进行数据的插入、修改、删除操作。

2.实验内容和要求

针对数据库设计单元组插入,批量数据插入、修改数据和删除数据等SQL语句。理解和掌握INSERT、UPDATE和DELETE语法结构的各个组成成分,结合嵌套SQL子查询,分别设计几种不同形式的插入、修改和删除数据的语句,并调试成功。

3.实验重点和难点

实验重点:插入、修改和删除数据的SQL。

实验难点:与嵌套SQL子查询相结合的插入、修改和删除数据的SQL语句;利用一个表的数据来插入、修改和删除另外一个表的数据。

4.实验过程

(1)插入单个元组

不指明属性列,按照顺序插入单个元组。

INSERT
INTO Student
VALUES("202015705","张玥","男",20,"MA");

指明属性列,没有赋值的属性列将自动赋空值。

INSERT 
INTO SC(Sno,Cno)
VALUES("202015705","9");

(2)插入子查询结果

对每一个课程,求课程的平均成绩,并把结果存入数据库。

CREATE TABLE C_avg_grade(
	Cno CHAR(9),
  	avg_grade SMALLINT  
);
INSERT 
INTO C_avg_grade(Cno,avg_grade)
SELECT Cno,AVG(GRADE)
FROM SC
GROUP BY Cno;

(3)修改单个或多个元组的值

将学生"刘晨"的年龄改为21岁。

UPDATE Student
SET Sage=21
WHERE Sname="刘晨";

将所有学生的年龄+1。

UPDATE Student
SET Sage=Sage+1;

(4)带子查询的修改语句

将计算机科学系学生的成绩清0。

UPDATE SC
SET GRADE=0
WHERE Sno IN(
	SELECT Sno
    FROM Student
    WHERE Sdept="CS"
);

(5)删除单个或多个元组的值

删除学号为"202014019"的学生。

DELETE
FROM Student
WHERE Sno="202014019";

删除所有选课记录。

DELETE
FROM SC;

(6)带子查询的删除语句

删除计算机科学系学生的选课记录。

DELETE 
FROM SC
WHERE Sno IN(
	SELECT Sno
    FROM Student
    WHERE Sdept="CS"
);

5.实验总结

更新或删除数据时,需要考虑完整性约束,此时该表中还没有添加约束,因此暂时没有考虑。在使用带有子查询的更新时,更新的表不能在查询中也使用,需要借助临时表进行更新。

6.思考题

(1)请分析数据库模式更新和数据更新SQL语句的异同。

两种语句都会改变数据库中的数据。数据库模式更新使用ALTER语句,改变的是关系模式。数据更新使用UPDATE语句,改变的是关系的值。

(2)请分析数据库系统除了INSERT、UPDATE和DELETE等基本的数据更新语句,还有哪些可以用来更新数据库基本表数据的SQL语句?

MERGE INRO语句可以用来更新或插入基本表。用法如下:

merge into products p using newproducts np on (p.product_id = np.product_id) 
when matched then 
update set p.product_name = np.product_name 
when not matched then 
insert values(np.product_id, np.product_name, np.category) 

TRUNCATE语句可以用于清空表:

truncate table tbl_name

实验 1.5 视图实验

1.实验目的

熟悉SQL语言有关视图的操作,能够熟练使用SQL语句来创建需要的视图,定义数据库外模式,并能使用所创建的视图实现数据管理。

2.实验内容和要求

针对数据库模式的相应应用需求,创建视图和带WITH CHECK OPTION的视图,并验证视图WITH CHECK OPTION选项的有效性。理解和掌握视图消解执行原理,掌握可更新视图和不可更新视图的区别。

3.实验重点和难点

实验重点:创建视图。

实验难点:可更新的视图和不可更新的视图之区别,WITH CHECK OPTION的验证。

4.实验过程

(1)创建视图

省略视图列名,建立计科专业学生的视图,该视图由单个表导出,且保留了主码,为行列子集视图

CREATE VIEW CS_Student
AS
SELECT Sno,Sname,Sage,Sdept
FROM Student
WHERE Sdept="CS";

建立学号和平均成绩的视图,这种视图带有聚集函数和GROUP BY子句查询,称为分组视图

CREATE VIEW S_G(Sno,avg_grade)
AS
SELECT Sno,AVG(GRADE)
FROM SC
GROUP BY Sno;

(2)建立视图(WITH CHECK OPTION)

使用WITH CHECK OPTION,建立计科专业学生的视图。

CREATE VIEW CS_Student
AS
SELECT Sno,Sname,Sage,Sdept
FROM Student
WHERE Sdept="CS"
WITH CHECK OPTION;

通过该视图对计科专业学生的记录分别进行增加,删除,修改。

/*不满足Sdept="CS",CHECK OPTION FAILED,不能增加*/
INSERT 
INTO CS_Student
VALUES("201902156","张权",21,"EE");
/*增加*/
INSERT 
INTO CS_Student
VALUES("201902156","张权",21,"CS");
/*删除*/
DELETE
FROM CS_Student
WHERE Sname="张权";
/*不满足CHECK OPTION的修改*/
UPDATE CS_Student
SET Sdept="EE"
WHERE Sname="刘晨";
/*修改*/
UPDATE CS_Student
SET Sage=22
WHERE Sname="刘晨";

(3)可更新的视图

建立机械专业学生的视图。并对其进行更新。

/*建立视图*/
CREATE VIEW ME_Student
AS
SELECT Sno,Sname,Sage
FROM Student
WHERE Sdept="ME";
/*增加*/
INSERT 
INTO ME_Student
VALUES("201802056","张三",21);
/*修改*/
UPDATE ME_Student
SET Sage=22
WHERE Sname="张三";
/*删除*/
DELETE
FROM ME_Student
WHERE Sname="张三";

以上的行列子集视图是可以更新的,因为视图中的属性和子查询中的表达式无关,所以可以进行任何增加,删除和修改。下面建立一个视图,仍然是机械专业学生的视图,但视图的属性列Sdept在建立视图的子查询中出现了。

CREATE VIEW ME_Student
AS
SELECT Sno,Sname,Sage,Sdept
FROM Student
WHERE Sdept="ME";
/*插入*/
INSERT
INTO ME_Student
VALUES("201802056","张三",21,"CS");
/*删除*/
DELETE
FROM ME_Student
WHERE Sname="张三";

对以上视图插入一个计科专业的学生,可以正常插入,因为没有添加WITH CHECK OPTION,更新的行不满足视图定义也可以插入,对视图的插入会通过视图消解转换为对基本表的插入。因此完成插入后,基本表中可以查询到插入的元组,但视图中查询不到,也不能在视图中删除该元组。

(4)不可更新的视图

一般情况下,只有行列子集视图是可以更新的,如果视图由两个表导出,或定义中含有聚集函数和GROUP BY子句,以及定义中含有DISTINCT短语等情况,视图都是不可更新的。例如对(1)中建立的学号和平均成绩的视图就是不可更新的,因为使用了聚集函数,不可以通过修改其他数据将平均成绩修改。

/*不可以对该视图进行更新*/
INSERT
INTO S_G
VALUES("201714021",80);

(5)删除视图

创建学生选课明细视图V_SC,列出学生学号,姓名,课程,课程类型,成绩,在该视图的基础上创建平均专业核心课成绩视图V_avgGrade,列出学生学号,姓名,核心课程成绩。分别利用RESTRICT 选项和CASCADE选项删除V_SC。

/*创建选课明细视图V_SC*/
CREATE VIEW V_SC
AS
SELECT S.Sno,S.Sname,C.Cname,C.Ctype,SC.GRADE
FROM Student S,Course C,SC
WHERE S.Sno=SC.Sno AND C.Cno=SC.Cno;
/*创建平均核心课成绩视图V_avgGrade*/
CREATE VIEW V_avgGrade(Sno,Sname,avg_grade)
AS
SELECT Sno,MAX(Sname),AVG(GRADE)
FROM V_SC
WHERE Ctype="专业核心"
GROUP BY Sno;
/*RESTRICT删除*/
DROP VIEW V_SC RESTRICT;
/*CASCADE删除*/
DROP VIEW V_SC CASCADE;

使用RESTRICT删除后,V_SC视图被删除,V_avgGrade没有被删除,但不能进行查询了。使用CASCADE删除的情况是一样的。在MYSQL的文档中,对于DROP VIEW语句有如下补充:RESTRICT and CASCADE, if given, are parsed and ignored.因此MYSQL中在删除视图时RESTRICT和CASCADE选项无效。

5.实验总结

视图可以简化用户查询,并可以提供一定的安全保护,向用户隐藏一些数据。视图是虚表,查询与更新都需要通过视图消解,转换为对基本表的查询与更新。通常行列子集视图是可以更新的。

6.思考题

(1)请分析视图和基本表在使用方面有哪些异同,并设计相应的例子进行验证。

视图是虚表,而基本表是存在的表。视图不占用物理空间,只存在于数据字典当中。使用视图和表的基本方法一样,但视图可能无法更新。视图的删除不会对基本表产生影响,但基本表删除后会导致视图无效。

/*创建一个视图*/
CREATE VIEW v_stu_grade
AS
SELECT student.sno,AVG(grade) avg_grade
FROM SC,Student
GROUP BY student.sno; 
/*该视图是不可更新的*/
UPDATE v_stu_grade
SET avg_grade = 100;	  /*无法执行*/
/*删除基本表,该视图将无法查询*/
DROP TABLE SC;
SELECT * FROM v_stu_grade;/*无法执行*/

(2)请具体分析修改基本表的结构对相应的视图产生何种影响。

如果修改基本表中,出现在视图的条件子句中的列的结构,会导致视图无效,如果修改结构但与视图涉及的列无关,则不影响视图。

实验 1.6 索引实验

1.实验目的

掌握索引设计原则和技巧,能够创建合适的索引以提高数据库查询、统计分析效率。

2.实验内容和要求

针对给定的数据库模式和具体应用需求,创建唯一索引、函数索引、符合索引等;修改索引;删除索引。设计相应的SQL查询验证索引有效性。学习利用EXPLAIN命令分析SQL查询是否使用了所创建的索引,并能够分析其原因,执行SQL查询并估算索引提高查询效率的百分比。要求实验数据集达到10万条记录以上的数据量,以便验证索引效果。

3.实验重点和难点

实验重点:创建索引。

实验难点:设计SQL查询验证索引有效性。

4.实验过程

为了验证索引效果,需要数据量足够大,因此使用实验指导提供的零件供应商模式。该模式包括Part,Supplier和PartSupp三个基本表。

建立如下:

CREATE SCHEMA PS;
USE PS;
CREATE TABLE Supplier(/*供应商基本表*/
	suppkey INTEGER PRIMARY KEY,
    sname CHAR(25),
    address VARCHAR(40),
    nationkey INTEGER,
    PHONE CHAR(15),
    acctbal REAL,
    comment VARCHAR(101)
);
CREATE TABLE Part(/*零件基本表*/
	partkey INTEGER PRIMARY KEY,
    pname VARCHAR(55),
    mfgr CHAR(25),
    brand CHAR(10),
    type VARCHAR(25),
    size INTEGER,
    container CHAR(10),
    retailprice REAL,
    comment VARCHAR(23)
);
CREATE TABLE PartSupp(/*零件供应联系表*/
	partkey INTEGER REFERENCES Part(partkey),
    suppkey INTEGER REFERENCES Suppliers(suppkey),
    availqty INTEGER,
    supplycost REAL,
    comment VARCHAR(199),
    PRIMARY KEY(partkey,suppkey)
);

(1)创建唯一索引

在供应商基本表建立供应商名的唯一索引。

CREATE UNIQUE INDEX idx_supplier_name ON Supplier(name);

(2)创建复合索引

在零件表的制造商和品牌两个字段上创建一个复合索引。

CREATE UNIQUE INDEX idx_part_mfgr ON Part(mfgr,brand);

(3)创建函数索引

对某个属性的函数创建索引,称为函数索引。

函数索引用适用于一种情况:被索引的列或列集合包含在某个表达式或是函数中,而表达式又经常出现在WHERE子句或ORDER BY子句中。

例如有一个表t,包含a,b两个字段,并且经常要执行类似的如下的查询:

SELECT *
FROM t
WHERE a*b>100;

为了加速查询,就可以创建如下函数索引:

CREATE INDEX idx ON t(a*b);

综上,如果查询条件为一个表达式,且经常进行查询,就可以添加函数索引。

在零件供应联系表上创建一个函数索引。

CREATE INDEX idx_part_name_fun 
ON 
PartSupp((supplycost/availqty));

(4)创建聚簇索引

聚簇存取方法:

为了提高某个属性或属性组的查询速度,把这个或这些属性上具有相同值的元组集中存放在连续的物理块中称为聚簇。该属性称为聚簇码。聚簇功能可以大大提高按聚簇码查询的效率。例如查询信息系的学生,尽管按照系的信息建立了索引,但数据可能分布在不同的物理块上,需要多次I/O。如同一系的学生集中存放,就能减少访问磁盘的次数。

聚簇索引:

使用CLUSTER语句可以使数据库管理系统根据指定的索引将表聚集,即让表按索引信息的顺序排序。建立聚簇索引必须在表中已有索引,然后根据索引使表聚集。在MYSQL使用的InnoDB中,主键将作为聚簇索引,如果表没有主键,MySQL将搜索UNIQUE所有键列所在的第一个索引,并将此UNIQUE索引用作聚簇索引。如果InnoDB表没有主键或合适的UNIQUE索引,MySQL会在内部生成一个隐藏的聚簇索引GEN_CLUST_INDEX,值为行ID。

以下是使用CLUSTER建立聚簇索引的语句,在PostgreSQL中可以执行。

在零件表的制造商字段上创建一个聚簇索引。

CREATE UNIQUE INDEX idx_part_mfgr ON Part(mfgr);
CLUSTER idx_part_mfgr ON Part;

(5)创建Hash索引

在供应商表的名称字段上创建一个Hash索引。

CREATE INDEX idx_supplier_name_hash USING HASH ON Supplier(sname);

MYSQL提示存储引擎不支持HASH索引。经查询,MYSQL使用InnoDB,用户无法手动创建HASH索引,但InnoDB会自调优,如果判断建立自适应哈希索引能够提升查询效率,InnoDB会自己建立相关的哈希索引。

(6)修改索引名称

修改供应商表的名称字段的索引名。

ALTER TABLE supplier RENAME INDEX idx_supplier_name TO idx_supplier_name1;

(7)分析某个SQL查询语句执行时是否使用了索引

EXPLAIN SELECT * FROM supplier WHERE sname="上海江宏路基材料有限公司";

从EXPLAIN语句的结果可以确认以上查询使用了供应商表的名称字段的索引。

 (8)验证索引效率

创建一个TestIndex,计算SQL查询执行的时间。

/*开启了bin-log, 需要制定函数类型*/
SET GLOBAL log_bin_trust_function_creators = 1;
/*delimiter // 的意思是把 // 当作结束符,mysql在编译的时候就不会因为语句中有多个符号而报错。*/
delimiter //
CREATE 
FUNCTION TestIndex(p_partname CHAR(55)) RETURNS INTEGER
BEGIN
	DECLARE begintime,endtime TIMESTAMP(3);
	DECLARE durationtime,result INTEGER;
	SELECT current_timestamp(3) INTO begintime;
	SELECT partkey FROM Part WHERE pname=p_partname INTO result ;
	SELECT current_timestamp(3) INTO endtime;
	select TIMESTAMPDIFF(MICROSECOND,begintime,endtime) INTO durationtime;
	RETURN durationtime;
END//
delimiter ;

先查看零件表Part数据规模比较小,并且无索引时的执行时间。发现返回值是0。

/*查看当零件表Part数据规模比较小,并且无索引时的执行时间*/
SELECT TestIndex("单轴振动筛");

TIMESTAMPDIFF仅支持到秒的精度,在这个精度无法比较有无索引对查询速度的影响,因此不使用函数进行比较,直接查看SQL语句执行的duration time比较查询时间。

倍增零件表的数据,这里直接倍增到了百万级别。

INSERT 
INTO Part
	SELECT partkey + 100*(SELECT COUNT(*) FROM Part),
		pname,mfgr,brand,type,size,container,retailprice,comment
	FROM Part;

 先在无索引的情况下执行以下查询,用时32ms

select * from part where pname="压滤机";

 创建零件表名称的索引,然后再执行查询。用时小于ms级。

CREATE INDEX idx_partname ON Part(pname);
select * from part where pname="压滤机";

通过以上的比较,尽管不能计算创建索引后查询效率提高的百分比,但可以验证创建索引后,查询效率明显提高了。

5.实验总结

创建索引可以显著提高查询效率。索引有多种,包括唯一索引,复合索引,函数索引,Hash索引等。通过实验可以看出,存储引擎会使用索引加速查询,对于如何建立一些类型的索引,不同的存储引擎有不同的策略。

6.思考题

在一个表的多个字段上创建的复合索引,与在相应的每个字段上创建的多个简单索引有何异同?请设计相应的例子加以验证。

复合索引和多个简单索引都能加快查询速度。差别使用以下的例子来说明。

假设创建一个组合索引和一个单个索引。

CREATE INDEX combined_idx ON Student(Sdept,Sname);
CREATE INDEX single_idx ON Student(Sdept);

使用以下两个查询时:

EXPLAIN SELECT * FROM student WHERE Sdept='CS' AND Sname = '王欣';
EXPLAIN SELECT * FROM student WHERE  Sdept = 'CS';

 两个索引都包含了Sdept,但MYSQL在第二次搜索时没有使用单个列的简单索引,而是使用了复合索引。如果使用多个条件查询而没有复合索引时,就只能使用单个索引,会降低查询速度。

再建立一个单独的索引,进行查询:

CREATE INDEX single_idx2 ON Student(Sname);
EXPLAIN SELECT * FROM student WHERE  Sname = '王欣';

 可以看到这次使用的是单个索引,而不是复合索引。这是因为创建复合索引时,会先按复合索引中的第一列进行排序,然后使用第二列排序。在以上的查询中,Sname是复合索引的第二列,因此不如直接使用单个索引。从以上例子可以看出索引中的所有列执行搜索或仅对前几列执行搜索时,复合索引更快且会被使用;仅对后面的任意列执行搜索时,复合索引没有作用,使用单个索引才能提高查询速度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/96712.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第十七届D2大会(I)

一、Web Compass-端内Web App解决方案揭秘 增强传统web端内方案&#xff0c;提供更好、更收敛的工程体验 二、自渲染跨端框架在字节跳动的实践与展望 基于Flutter Engine的二次开发 三、Qking&#xff1a;跨端JS引擎的深度探索与突破 常见js引擎&#xff0c;如&#xff1a;v8…

CSC7268

CSC7268概述: CSC7268是一款内置高压MOS的高性能、多工作模式的PWM控制芯片&#xff0c;内置多种保护机制。当系统为空载和轻载时&#xff0c;CSC7268采用Burst和Green控制模式可有效地减少了空载和轻载时的损耗。当系统为中载和重载时&#xff0c;芯片采用QR模式和CCM模式可有…

python基础: filter, lambda 函数表达式

filter(function or None, sequence)&#xff0c;其中sequence 可以是list ,tuple,string。这个函数的功能是过滤出sequence 中所有以元素自身作为参数调用function时返回True或bool(返回值)为True的元素并以列表返回. filter只能接受两个参(function,sequence) &#xff0c;其…

Biotin-PEG-SH,Biotin-PEG-Thiol,生物素PEG巯基PEG衍生物供应

英文名称&#xff1a;Biotin-PEG-Thiol&#xff0c;Biotin-PEG-SH 中文名称&#xff1a;生物素-聚乙二醇-巯基 生物素-PEG-SH通过与链霉亲和素或抗生物素结合进行聚乙二醇化&#xff0c;具有高亲和力和特异性。生物素通过稳定的酰胺连接物与线性PEG结合。它具有与马来酰亚胺选…

java 瑞吉外卖day3 公共字段自动填充 新增分类

公共字段自动填充 代码实现 1. TableField(fill FieldFill.INSERT)//插入时填充字段 private LocalDateTime createTime;TableField(fill FieldFill.INSERT_UPDATE)//插入和更新时填充字段 private LocalDateTime updateTime;TableField(fill FieldFill.INSERT) private Lo…

数据库实验六:存储过程实验

实验六 存储过程实验 实验6.1 存储过程实验 1.实验目的 ​ 掌握数据库PL/SQL编程语言&#xff0c;以及数据库存储过程的设计和使用方法。 2.实验内容和要求 ​ 存储过程定义&#xff0c;存储过程运行&#xff0c;存储过程更名&#xff0c;存储过程删除&#xff0c;存储过程…

[附源码]Python计算机毕业设计Django少儿节目智能推荐系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Oracle数据的备份和恢复

Oracle数据的备份和恢复 ​ 当我们使用一个数据库时,总希望数据是可靠的、正确的,但由于计算机系统的故障(硬件故障、软件故障、网络故障、进程故障和系统故障)影响数据库系统的操作,影响数据库中数据的正确性,甚至破坏数据库,使数据库中全部或部分数据丢失。因此当发生上述故…

logistic回归的标准化回归系数 计算方式

创建于&#xff1a;2022.12.17 修改于&#xff1a;2022.12.17 文章目录1、未标准化回归系数2、标准化回归系数3、两者的区别4、手动计算5、计算样例6、参考资料1、未标准化回归系数 通常我们在构建多因素回归模型时&#xff0c;方程中呈现的是未标准化回归系数&#xff0c;它是…

【财务】财务分析---管理报告体系搭建

财务分析体系搭建的是一个系统化的功能&#xff0c;涉及的业务面非常广&#xff0c;财务分析也能表现出清晰的数据&#xff0c;以此进行改善&#xff1b;本文作者详细分析了财务分析中的管理报告体系的搭建&#xff0c;我们一起来看一下。 一、理清核算、财报、管报、预算关系 …

java设计模式(下)

文章目录第六章 行为型模式(11种)6.1 观察者模式6.1.1 观察者模式介绍6.1.2 观察者模式原理6.1.3 观察者模式实现6.1.4 观察者模式应用实例6.1.5 观察者模式总结6.2 模板方法模式6.2.1 模板方法模式介绍6.2.2 模板方法模式原理6.2.3 模板方法模式实现6.2.4 模板方法模式应用实例…

计算机网络——PPP协议与HDLC协议

广域网 广域网通常跨接很大的1物理范围&#xff0c;所覆盖的范围从几十公里到几千公里&#xff0c;他能链接多个城市或者国家&#xff0c;并且横跨几个州并能提供远距离通信。 广域网的通信子网使用的分组交换技术&#xff0c;广域网的通信子网可以利用公用分局交换网&#xf…

我也“阳”了

大家好&#xff0c;我是哪吒&#xff0c;我也“阳”了&#xff0c;现在是北京时间2022年12月17日 18:36&#xff0c;这篇文章简单说一下我“阳”了的经历和感受。 昨天下午&#xff0c;发现嗓子疼&#xff0c;不舒服&#xff0c;喝了很多茶水&#xff0c;喝了一瓶蓝芩口服液&a…

【大数据技术Hadoop+Spark】Spark RDD设计、运行原理、运行流程、容错机制讲解(图文解释)

一、RDD的概念 RDD&#xff08;Resilient Distributed Dataset&#xff09;&#xff0c;即弹性分布式数据集&#xff0c;是一个容错的、并行的数据结构&#xff0c;可以让用户显式地将数据存储到磁盘和内存中&#xff0c;并且还能控制数据的分区。不同RDD之间可以通过转换操作…

SLAM 几何基础

SLAM 几何基础1. 向量运算及其几何意义1.1 内积1.1.1 内积定义1.1.2 内积几何意义1.1.3 内积微分性质1.2 外积1.2.1 外积定义1.2.2 外积几何意义1.2.3 外积微分性质2. 线面特征运算2.1 点到直线距离2.2 点到平面距离Reference:深蓝学院-多传感器融合 1. 向量运算及其几何意义 …

QT系列第4节 QT包含模块以及常用的数据类型和容器

QT中包含很多模块&#xff0c;这些模块都是建立在常用数据类型和容器基础之上的。本篇简单介绍一下常用模块&#xff0c;常用数据类型&#xff0c;常用容器类。 目录 1.QT模块分类 2.QT基本数据类型 3.QString和QByteArray区别 4.QT中的容器 1.QT模块分类 &#xff08;1&…

jdk11新特性——更简化的编译运行程序

目录一、概述二、注意事项三、注意事项1——代码示例3.1、示例13.2、示例23.3、示例3四、注意事项2——代码示例4.1、示例14.2、示例2一、概述 JEP 330 : 增强java启动器支持运行单个java源代码文件的程序。 在我们的认知里面&#xff0c;要运行一个 Java 源代码必须先编译&am…

CentOS 8:FTP服务器

FTP服务器 vsftpd , 是 CentOS 系统自带的 FTP 服务 其中&#xff0c;d 表示 daemon , 后台、守护进程的意思 FTP文件传递示意图&#xff1a; 检查 vsftpd 是否安装 ls /usr/sbin/vsftpd 安装vsftpd软件包 yum install vsftpd 其中&#xff0c;yum 是 CentOS 下的软件包…

低代码平台丨仪表盘实用技巧—【倒计时】

学生时代&#xff0c;我们经常能够看到所谓的中考倒计时、高考倒计时…… 这些白纸黑字的倒计时看板&#xff0c;不仅贯穿着我们的学生生涯。在步入职场之后&#xff0c;随之而来的项目倒计时、季度倒计时&#xff0c;年度倒计时……各种各样的倒计时看板&#xff0c;充斥着我…

卷积神经网络-基础篇Basic-CNN

卷积神经网络-基础篇Basic-CNN CNN的全称是"Convolutional Neural Network"(卷积神经网络)。而神经网络是一种模仿生物神经网络&#xff08;动物的中枢神经系统&#xff0c;特别是大脑&#xff09;结构和功能的数学模型或计算模型。 CNN原理 CNN被广泛应用在图像识…