面试被问到的各种问题(一直更新,比较忙)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_41813228/article/details/80372387

1. 你用过哪些异步框架
    swoole
2. php中如何实现多继承

 可以使用trait,trait本身无法实例化 

传送门:http://php.net/manual/zh/language.oop5.traits.php;

3. 为什么要用302重定向,了解DNS劫持吗,原理是什么

一般使用302重定向是在一个网站或者一个网页24到48小时内临时转移到其他位置的情况下使用该命令,这个时候是做临时性的跳转,302重定向容易被搜索引擎认为是多个域名指向同一个网站,容易被用作url劫持。

重定向之后,搜索引擎会抓取新的页面内容而保留旧的网址,

301永久重定向则是新的内容新的网址

DNS是将网络地址(域名)对应的真实的、计算机能够识别的网络地址(IP),以便计算机能够进一步通信,传送数据等 

域名服务器上保持着所有的域名--IP 的记录,当域名服务器收到查询请求后,会在缓存、数据库中查询对应的记录,然后把结果数据返回给客户端;

如果有人(hacker) 恶意修改了记录的内容,让域名解析到了错误的IP 地址,这时域名就解析到了错误的IP(有可能是竞争对手的网页),这就是域名劫持.

4.  面向对象的概念及意义,三个特性的应用场景,五大基本原则

 面向过程是一种思想,将流程分解成小功能,然后用函数对功能进行封装,使用的时候调用函数去实现,代码很乱,不易管理

面向对象是将常用的操作进行类封装,使用的直接调用,修改这个封装的类就可以直接修改全站,易于开发维护

共同点:都是实现模块化编程,都能实现代码的 重用

不同点:面向过程效率比面向对象高,面向过程可以直接调用函数;面向对象必须先得到主体(对象),再调用内部函数

面向对象的三个特征:封装、继承、多态

封装:就是讲客观事物封装成抽象的类,一个类就是封装了数据及操作这些数据的代码的逻辑实体(使类更加安全)

继承: 继承性就是从一个基类(父类)派生出来的派生类(子类),继承可以使得子类具有父类的各种属性和方法,而不需要再次编写相同的代码。在令子类继承父类的同时,可以重新定义某些属性,并重写某些方法,即覆盖父类的原有属性和方法,使其获得与父类不同的功能。(重写、拓展)

多态:实现多态的前提是实现继承,一个类被多个子类继承,如果这个类的某个方法在多个子类中表现出 不同的功能,这种行为就叫多态

实现多态的途径:子类继承父类,重写父类方法,父类引用指向子类对象

可以参考:https://blog.csdn.net/xiaobaitu389/article/details/76068145

五大基本原则

单一职责原则:类的功能要单一

开放封闭原则:一个模块在扩展性方面应该是开放的而在更改性方面应该是封闭的。比如:一个网络模块,原来只服务端功能,而现在要加入客户端功能,

那么应当在不用修改服务端功能代码的前提下,就能够增加客户端功能的实现代码,这要求在设计之初,就应当将服务端和客户端分开,公共部分抽象出来。

替换原则:子类可以替换父类并出现在父类能够出现的地方

依赖原则(具体依赖抽象,上层依赖下层)

假设B是较A低的模块,但B需要用到A的功能,这时B不应直接使用A的具体类,而应该由B定义一个抽象接口,并由A去实现这个接口,B只使用这个接口,这样就达到了依赖倒置的关系,B也解除了对A的依赖,反过来是A依赖于B定义的抽象接口,通过上层模块难以避免依赖下层模块,假如B也直接依赖于A的实现,那么久造成了循环依赖,最常见的就是编译A模块时需要直接包含到B模块的cpp文件,而编译B时也要包含到A的cpp文件

接口分离原则:模块间要通过抽象接口分离开,而不是通过具体的类强耦合起来

7.数据库中的悲观锁、乐观锁

数据库管理系统的并发控制的任务是确保多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性,乐观锁和悲观锁是并发控制的主要技术手段

数据库中的悲观锁,每次拿数据的时候都会认为别人会修改数据,所以一般都会加锁。确保自己使用的时候不会被访问,直到使用完毕解锁,期间访问 该数据的都会等待
乐观锁,每次拿数据的时候都不担心别人会修改,所以每次在拿数据的时候都不会加锁,但是在更新的时候会判断在此期间有没有人修改过数据,可以使用版本号等机制,适用于多读的应用类型,这样可以提高吞吐量,像数据库的write_condition机制的其实都是乐观锁
两种锁各有优缺点,像乐观锁适用于写少的情况,这样可以节省锁的开销,加大了系统的吞吐量,但是如果经常发生冲突,上层应用不断的retry,这样反倒是降低了性能,这种情况下适用悲观锁就更合适

8.redis和memache的缓存机制
11.请描述一下项目后端架构 
13.物流跟踪的实现流程
14.拆单的实现
15.如何保证添加进购物车和生成订单中的商品价格和当时添加商品的价格保持一致
16.ajax的跨域问题
19.反爬虫的实现
20.php与nginx的交互原理
21.php的缓存机制
22.如何将文字和图片一起存入数据库
23.如何上传一个大文件或者视频到服务器
24.读取一个1个G的文件
25.laravel、TP、CI框架实现流程
31.进程与线程    
32.对memcach的理解

memcach是一种缓存技术,在一定的时间内将动态网页经过解析之后保存到文件,下次访问动态网页时就自动调用这个文件,而不必重新访问数据库,好处是提高页面的访问速度,减轻高并发时服务器的压力

优点:稳定、配置简单、多机分布式存储,速度快

26.面向对象中接口和抽象类的区别及应用场景

有抽象方法的类叫做抽象类,抽象类不一定有抽象方法,抽象方法必须使用abstruct关键字进行定义

接口中全是抽象方法,不用abstract定义

当多个同类的类要设计一个上层,通常设计为抽象类,当多个异构的类要设计一个上层,通常设计为接口

27.三次握手、四次挥手

三次握手:建立连接时,客户端发送syn到服务器,并进入syn_sent状态,等待服务器确认;服务器收到syn包,必须确认客户端的syn包(ack=j+1),并发送syn+ack包,此时服务器进入syn_recv状态;客户端收到服务器端的syn+ack包后,向服务器发送确认包ack(ack=k+1),此包发送完毕,客户端和服务器端进入链接状态,三次握手完毕

四次挥手:当主机A的应用告诉TCP数据传送完成时,TCP向主机B发送一个fin(finish)附加标记的报文段;当主机B收到这个fin报文段,并不立即用fin报文段回复主机A,而是 先向主机A发送一个确认序号ack,同时通知自己的应用程序,对方要求关闭连接(发送ack的目的是防止这段时间内对方重新发送fin报文段);主机B的应用程序告诉TCP:我要关闭连接,TCP发送一个fin报文段给主机A;主机A收到这个fin报文段后,向主机B发送一个ack表示连接释放

28.tcp、udp的区别


29.一次完整的网络请求

分析域名

tcp的三次握手

建立TCP连接后,浏览器发送http请求

服务器响应请求

服务器解析html数据并请求其中的其他资源

浏览器进行页面渲染呈现给用户

30.魔术方法及作用

__call()    当调用不存在的方法时自动调用的方法

__autoload()    在实例化一个尚未定义的类时会自动调用该方法来加载类文件

__set()    当给未定义的变量赋值时自动调用的方法

__get()    当获取未定义变量的值时自动调用的方法

__construct()    构造方法,实例化类时自动调用的方法

__unset()    当对一个未定义的变量调用unset()时自动调用的方法

__isset()    当对一个未定义的变量调用isset()时自动调用的方法

__clone()    克隆一个对象

__tostring()    当输出一个对象时自动调用的方法

34.大流量高并发网站的解决方案

确认当前服务器硬件是否能够支持当前的流量

使用memcach缓存技术,将动态数据缓存到内存中,动态网页直接调用这些文件而不必再次访问数据库

禁止外部盗链,外部网站的图片或者文件盗链往往会带来大量的负载压力,目前可以通过refer来控制盗链,Apache可以通过配置来禁止盗链

控制大文件的下载

使用不同的主机分流

分库分表

使用流量统计软件,可以及时知道哪些地方耗费了大量流量,哪些页面需要进行优化

35.如何设计和配置mysql,才能达到高效

数据库设计方面,设计结构良好的数据库,允许部分数据冗余,选取适用的字段属性,尽可能把字段设置为not null,这样查询时数据库不用去比较null值

系统架构设计方面,表散列,将海量数据散列到不同的表里面,做读写分离

使用表链接代替子查询

使用联合来代替手动临时创建的表

尽量少用select *,只取必须的数据

必要的时候使用不同的存储引擎,比如innodb可以减少死锁,HEAP可以提高一个数据级的查询速度

使用事务。外键。索引

36.SQL注入漏洞产生的原因,如何防止

程序开发过程中书写sql语句不规范,没有对特殊字符进行过滤,导致客户端可以通过post或get提交一些sql语句正常执行

开启配置文件中的magic_quotes_gps(将get、post或cookie的数据进行转义)和magic_quotes_runtime(所有的单引号、双引号、反斜杠、空字符都会被自动加上反斜杠进行转义)设置

过滤掉常见的数据库操作关键字(如select、insert)等,或通过系统函数addslashes进行数据的过滤

关闭全局变量注册    register_globals=off

提高数据库表或字段的命名技巧

控制错误信息,关闭错误提示信息,将错误信息保存到系统日志

使用mysqli或者pdo进行预处理

37.谈谈对mvc的认识

由模型、视图、控制器完成的应用程序

mvc是一种设计模式,它强制性的将输入、处理、输出分开,使用mvc程序被分为三个核心件:模型、视图、控制器。

视图是用户看到并与之交互的界面

模型表示企业数据和业务规则

控制器接受用户的输入并调用模型和视图去完成用户的需求

优点:低耦合性,高重用性和可适用性,较低的生命周期成本,快速部署,可维护。可扩展

缺点:没有明确的定义,完全理解不容易,不适合小型规模的应用程序

38.几个重要的php.ini选项

reigister_globals    全局变量注册

safe——mode    安全模式,用来限制文档的存取,控制外部程序的执行

safe_mode_exec_dir = string    次选项指定的文件夹路径会影响system、exec、popen、passthru,不影响shell_exec和“‘’”    

39.使用过哪些php框架,各自的优缺点

  1. ThinkPHP简称TP,TP借鉴了Java思想,基于PHP5,充分利用了PHP5的特性,部署简单只需要一个入口文件,一起搞定,简单高效。中文文档齐全,入门超级简单。自带模板引擎,具有独特的数据验证和自动填充功能,框架更新速度比较速度。

    优点:这个框架易使用 易学 安全 对bae sae支持很好提供的工具也很强大 可以支持比较大的项目开发 易扩展 全中文文档 总的来说这款框架适合非常适合国人使用 性能 上比CI还要强一些

    缺点:配置对有些人来说有些复杂(其实是因为没有认真的读过其框架源码)文档有些滞后 有些组件未有文档说明。

  2. CodeIgniter简称CI 简单配置,上手很快,全部的配置使用PHP脚本来配置,没有使用很多太复杂的设计模式,(MVC设计模式)执行性能和代码可读性上都不错。执行效率较高,具有基本的MVC功能,快速简洁,代码量少,框架容易上手,自带了很多简单好用的library。 框架适合中小型项目,大型项目也可以,只是扩展能力差。优点:这个框架的入门槛很底 极易学 极易用 框架很小 静态化非常容易 框架易扩展 文档比较详尽

    缺点:在极易用的极小下隐藏的缺点即是不安全 功能不是太全 缺少非常多的东西 比如你想使用mongoDB你就得自己实现接口… 对数据的操作亦不是太安全 比如对update和delete操作等不够安全 暂不支持sae bae等(毕竟是欧洲)对大型项目的支持不行 小型项目会非常好。

    CI和TP的对比(http://www.jcodecraeer.com/a/phpjiaocheng/2012/0711/309.html

  3. Laravel的设计思想是很先进的,非常适合应用各种开发模式TDD, DDD和BDD(http://blog.csdn.net/bennes/article/details/47973129 TDD DDD BDD解释 ),作为一个框架,它为你准备好了一切,composer是个php的未来,没有composer,PHP肯定要走向没落。laravel最大的特点和处优秀之就是集合了php比较新的特性,以及各种各样的设计模式,Ioc容器,依赖注入等。因此laravel是一个适合学习的框架,他和其他的框架思想有着极大的不同,这也要求你非常熟练php,基础扎实。

    优点:http://www.codeceo.com/article/why-laravel-best-php-framework.html

  4. Yii是一个基于组件的高性能的PHP的框架,用于开发大规模Web应用。Yii采用严格的OOP编写,并有着完善的库引用以及全面的教程。从MVC,DAO/ActiveRecord,widgets,caching,等级式RBAC,Web服务,到主体化,I18N和L10N,Yii提供了今日Web 2.0应用开发所需要的几乎一切功能。而且这个框架的价格也并不太高。事实上,Yii是最有效率的PHP框架之一。

40.xdebug

41.数据库设计时长遇到的瓶颈

① 磁盘搜索    优化方法:将数据分布在多个磁盘上

②磁盘读写     优化方法:从多个磁盘并行读写

③CPU周期    优化方法:扩充内存

④内存带宽

5.myisam与innodb的区别

基本的差别:MYISAM类型的表强调的是性能,执行效率比innodb快,innodb支持事务外键等高级数据库功能,myisam不支持。

细节:

① innodb中不保存表的具体行数,比如 select count(*) from table时,innodb会扫描整个表来计算一共有多少行,但是myisam只要简单的读出保存的行数就可以,注意,当count(*)语句包含where条件时,两种表的操作是一样的

②对于AUTO_INCREMENT类型的字段,innodb中必须包含只有该字段的索引,但是myisam表中,可以和其他字段一起建立联合索引

③delete from table时,innodb不会重新建立表,而是一行一行的删除

④load data from master 操作对innodb不起作用,解决方法是先将innodb表改成myisam,导入数据后再改成innodb表,但是对于额外的innodb特性(例如外键)不适用

⑤另外,InnoDB表的行锁也不是绝对的,假如在执行一个SQL语句时MySQL不能确定要扫描的范围,InnoDB表同样会锁全表,例如update table set num=1 where name like “%aaa%”

两者最主要的差别是innodb支持事务处理与外键和行级锁,而myisam不支持,所有myisam往往被认为只能在小项目中使用

作为使用MySQL的用户角度出发,Innodb和MyISAM都是比较喜欢的,如果数据库平台要达到需求:99.9%的稳定性,方便的扩展性和高可用性来说的话,MyISAM绝对是首选。

原因:

①平台上承载的项目大多是读多于写的,而myisam的读性能比innodb强(原因参考:https://blog.csdn.net/leyangjun/article/details/49721351)

②myisam中的索引和数据是分开的,并且索引式压缩的,所以内存使用率提高了不少,能加载更多索引,innodb索引和数据是捆绑的,且没有压缩,索引innodb比myisam体积大不少

③经常隔1,2个月就会发生应用开发人员不小心update一个表where写的范围不对,导致这个表没法正常用了,这个时候MyISAM的优越性就体现出来了,随便从当天拷贝的压缩包取出对应表的文件,随便放到一个数据库目录下,然后dump成sql再导回到主库,并把对应的binlog补上。如果是Innodb,恐怕不可能有这么快速度,别和我说让Innodb定期用导出xxx.sql机制备份,因为最小的一个数据库实例的数据量基本都是几十G大小

④从接触到应用逻辑来看,select count(*)和order by是最频繁的,而这种操作innodb也是会锁表的,很多人认为innodb是行级锁,那个只是where主键对他有效,非主键的都会锁表

⑤还有就是经常有很多应用部门需要我给他们定期某些表的数据,MyISAM的话很方便,只要发给他们对应那表的frm.MYD,MYI的文件,让他们自己在对应版本的数据库启动就行,而Innodb就需要导出xxx.sql了,因为光给别人文件,受字典数据文件的影响,对方是无法使用的。

索引: myisam的索引和数据是分开的,并且索引是有压缩的,而innodb索引和数据是放到一起的,没有压缩,因而innodb比myisam体积更大,myisam每张表都包含三种文件:表定义文件(.frm)、数据文件(.myd)、索引文件(.myi),而innodb通常许多表保存在同一文件下,此外,如果表数据非常大,通常使用myisam。

6. 数据库用索引为什么比不用索引快

  1.  ①为什么需要索引     

    数据在磁盘上是以块的形式存储的,为确保对磁盘操作的原子性,访问数据的时候会一并访问所有的数据块,磁盘上的数据块和链表类似,即他们都包含一个数据段和一个指针,指针指向下一个节点(数据块)的内存地址,而且不需要连续存储

鉴于很多记录只能做到按一个字段排序,所以要查询某个未经排序的字段,就需要使用线性查找,即要访问N/2个数据块,其中N指的是一个表所涵盖的所有数据块。如果该字段是非键字段(也就是说,不包含唯一值),那么就要搜索整个表空间,即要访问全部N个数据块。

然而,对于经过排序的字段,可以使用二分查找,因此只要访问log2 N个数据块。同样,对于已经排过序的非键字段,只要找到更大的值,也就不用再搜索表中的其他数据块了。这样一来,性能就会有实质性的提升。

②什么是索引

索引是对纪录按照多个字段进行排序的一种方式,对表中的某个字段建立索引会创建另一种数据结构,其中保存着字段的值,每个值又指向和他相关的纪录,这种索引的数据结构是经过排序的,因此可以对其使用二分查找

索引的缺点是占用额外的磁盘空间,因为索引保存在MyISAM数据库中,所以如果为同一个表中的很多字段都建立索引,那这个文件可能会很快膨胀到文件系统规定的上限。

参考:http://www.ituring.com.cn/article/986 https://www.2cto.com/database/201211/172380.htm

https://www.cnblogs.com/uttu/p/6633939.htmll

9.索引的种类及应用场景(使用 show index from tablename 查看索引)

1.普通索引     

    create indexname on tablename(列的列表)

    alert  table tablename add index 【indexname】 on(列的列表) 

2.唯一索引(与普通索引类似,不同的是索引列的值必须唯一,但允许有空值,如果是组合索引,列值得组合必须唯一)

    create unique index indexname on tablename (列的列表)

3.主键索引(特殊的唯一性索引,必须指定为primary key)

4.组合索引

 使用索引的情景

① 快速查找符合where条件的纪录

②快速确定候选集,如果where 使用了多个索引字段,则会优先使用使候选集规模最下的索引字段以便尽快淘汰不符合条件的纪录

③多表做join操作时使用索引

MySQL只对一下操作符才使用索引:<,<=,=,>,>=,between,in以及某些时候的like(不以通配符%或_开头的情形)。

10.redis的主从实现原理
18.优化sql语句

 对查询进行优化,应尽量避免全表扫描,首先应该考虑在where和order by涉及的列上添加索引

尽量避免在where 子句中使用!=或<>操作符,否则引擎会放弃索引查询而选择全表扫描

拆分大的delete或insert操作,因为这两个操作会锁表

select * 尽量少用,想要什么字段就select什么字段,只要一条记录时尽量使用limit 1

需要用到text、varchar类型时,最好将text的字段单独放到一个表里,用主键关联

字段的种类尽可能用int或者tinyint类型。另外字段尽可能用not null

尽量避免在where子句中进行表达式操作,

explain你的select查询

很多时候用 exists 代替 in 是一个好的选择

应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,in 和 not in 也要慎用

  41.PHP中如何使用socket进行通信?

42.简单说一说delete、drop、truncate的区别

速度来说,drop>truncate>delete

delete和truncate只删除表的数据而不删除表的结构

delete是dml(数据操纵语句),这个操作会放到rollback segement中,事务提交之后才生效

drop和truncate是ddl(数据定义语言),操作立即生效,原数据不放到rollback segment中,不能回滚. 操作不触发trigger

43.什么是视图,视图的使用场景

视图是一种虚拟的表,和物理表类似,具有和物理表相同的功能,可以对视图进行增删改查,视图一般是一个或多个表的行或列的子集,对视图的修改不会影响基本表,它使我们获取数据更方便,相比多表查询

只暴露部分字段给访问者,所以就建一个虚表,也就是视图

查询的数据来源于不同的表,但是查询者希望以统一的方式进行查询,这样就可以建立一个视图,将来自不同表的数据集中起来,这样查询者就可以从视图中直接获取数据,不必考虑数据来源不同的表所带来的差异

44.视图与临时表

当一个数据库中存在大量的数据,而我们想要这个数据集合的一个子集,就可以使用临时表来保存数据

create    temporary    table     tmp_name    select    *    from    table_name    将查询的结果放入临时表中

临时表在我们与mysql断开连接的时候会自动删除并且释放空间,也可以手动删除    drop    table    tmp_name

临时表的使用是有限制的

i.临时表只能使用在memory,myisam,merge,innodb存储引擎下。。。

ii.临时表不支持mysql簇。。

iii.在同一个query语句中,我们只能查询一次临时表。。

iv.show table语句不会列举临时表信息..

v.不能使用rename来重命名一个临时表,但是我们可以使用alter table语句来代替..    

参考:https://www.cnblogs.com/RGogoing/p/4488925.html

45.msyql锁的 分类

按操作分:dml锁    ddl锁

按锁的粒度分:表级锁    行级锁    页级锁

按锁的级别分:共享锁    排它锁

按加锁方式分:自动锁    显示锁

按使用方式分:悲观锁    乐观锁

DML锁(data locks,数据锁),用于保护数据的完整性,其中包括行级锁(Row Locks (TX锁))、表级锁(table lock(TM锁))。 DDL锁(dictionary locks,数据字典锁),用于保护数据库对象的结构,如表、索引等的结构定义。其中包排他DDL锁(Exclusive DDL lock)、共享DDL锁(Share DDL lock)、可中断解析锁(Breakable parse locks)

46.什么是事务

并发控制的基本单位,它是一个操作序列,要么都执行,要么都不执行,事务是保护数据库一致性的单位,在每个事务结束时都能保证数据库的一致性

脏读:一个事务读取到另一个事务未提交的数据

例子:A向B转账,A执行了转账语句,但A还没有提交事务,B读取数据,发现自己账户钱变多了!B跟A说,我已经收到钱了。A回滚事务【rollback】,等B再查看账户的钱时,发现钱并没有多。

不可重复读:一个事务读取到另一个事务提交的数据,也就是说一个事务可以看到另一个事务所做的修改

注:A查询数据库得到数据,B去修改数据库的数据,导致A多次查询数据库的结果都不一样【危害:A每次查询的结果都是受B的影响的,那么A查询出来的信息就没有意思了

虚读(幻读):一个事务内读取到别的事务插入的数据,导致前后读取不一样

注:和不可重复读类似,但虚读(幻读)会读到其他事务的插入的数据,导致前后读取不一致

简单总结:脏读是不可容忍的,不可重复读和虚读在一定的情况下是可以的【做统计的肯定就不行】

47.数据表破坏的修复方式有哪些

使用repair    table    或者    optimize    table来修复

repair  table  tablename    修复表    optimize  table  tablename    优化表

OPTIMIZE TABLE 用于回收闲置的数据库空间,当表上的数据行被删除时,所占据的磁盘空间并没有立即被回收,使用了OPTIMIZE TABLE命令后这些空间将被回收,并且对磁盘上的数据行进行重排(注意:是磁盘上,而非数据库)

48.mysql中的innodb行锁是通过加在什么上实现的

innodb是基于索引完成行锁的

select    *    from    tablename    where    id=1     for update

for    update可以根据条件来完成行锁,并且id是有索引键的列

如果id不是索引键的列,那么就会完成表锁,并发将无从谈起

49.数据库优化的思路


49.数据库优化的思路 

SQL优化

在我们书写SQL语句的时候,其实书写的顺序、策略会影响到SQL的性能,虽然实现的功能是一样的,但是它们的性能会有些许差别。

因此,下面就讲解在书写SQL的时候,怎么写比较好。

①选择最有效率的表名顺序

数据库的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表将被最先处理

在FROM子句中包含多个表的情况下:

  • 如果三个表是完全无关系的话,将记录和列名最少的表,写在最后,然后依次类推
  • 也就是说:选择记录条数最少的表放在最后

如果有3个以上的表连接查询:

  • 如果三个表是有关系的话,将引用最多的表,放在最后,然后依次类推
  • 也就是说:被其他表所引用的表放在最后

例如:查询员工的编号,姓名,工资,工资等级,部门名

emp表被引用得最多,记录数也是最多,因此放在form字句的最后面


select emp.empno,emp.ename,emp.sal,salgrade.grade,dept.dname
from salgrade,dept,emp
where (emp.deptno = dept.deptno) and (emp.sal between salgrade.losal and salgrade.hisal)        

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

②WHERE子句中的连接顺序

数据库采用自右而左的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之左,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的之右

emp.sal可以过滤多条记录,写在WHERE字句的最右边


      select emp.empno,emp.ename,emp.sal,dept.dname
      from dept,emp
      where (emp.deptno = dept.deptno) and (emp.sal > 1500) 
  • 1
  • 2
  • 3
  • 4

③SELECT子句中避免使用*号

我们当时学习的时候,“*”号是可以获取表中全部的字段数据的。

  • 但是它要通过查询数据字典完成的,这意味着将耗费更多的时间
  • 使用*号写出来的SQL语句也不够直观。

④用TRUNCATE替代DELETE

这里仅仅是:删除表的全部记录,除了表结构才这样做

DELETE是一条一条记录的删除,而Truncate是将整个表删除,保留表结构,这样比DELETE快

⑤多使用内部函数提高SQL效率

例如使用mysql的concat()函数会比使用||来进行拼接快,因为concat()函数已经被mysql优化过了。

⑥使用表或列的别名

如果表或列的名称太长了,使用一些简短的别名也能稍微提高一些SQL的性能。毕竟要扫描的字符长度就变少了。。。

⑦多使用commit

comiit会释放回滚点…

⑧善用索引

索引就是为了提高我们的查询数据的,当表的记录量非常大的时候,我们就可以使用索引了。

⑨SQL写大写

我们在编写SQL 的时候,官方推荐的是使用大写来写关键字,因为Oracle服务器总是先将小写字母转成大写后,才执行

⑩避免在索引列上使用NOT

因为Oracle服务器遇到NOT后,他就会停止目前的工作,转而执行全表扫描

①①避免在索引列上使用计算

WHERE子句中,如果索引列是函数的一部分,优化器将不使用索引而使用全表扫描,这样会变得变慢

①②用 >= 替代 >

      低效:
      SELECT * FROM EMP WHERE DEPTNO > 3   
      首先定位到DEPTNO=3的记录并且扫描到第一个DEPT大于3的记录
      高效:
      SELECT * FROM EMP WHERE DEPTNO >= 4  
      直接跳到第一个DEPT等于4的记录
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

①③用IN替代OR


      select * from emp where sal = 1500 or sal = 3000 or sal = 800;
      select * from emp where sal in (1500,3000,800);
  • 1
  • 2
  • 3
  • 4

①④总是使用索引的第一个列

如果索引是建立在多个列上,只有在它的第一个列被WHERE子句引用时,优化器才会选择使用该索引。 当只引用索引的第二个列时,不引用索引的第一个列时,优化器使用了全表扫描而忽略了索引


      create index emp_sal_job_idex
      on emp(sal,job);
      ----------------------------------
      select *
      from emp  
      where job != 'SALES'; 


      上边就不使用索引了。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

数据库结构优化

  • 1)范式优化: 比如消除冗余(节省空间。。)
  • 2)反范式优化:比如适当加冗余等(减少join)
  • 3)拆分表: 垂直拆分和水平拆分

服务器硬件优化

这个么多花钱咯!

50.三个范式

范式一:数据库中的字段是单一属性,不可再分,这个单一属性由基本类型组成,包括整型、字符串型、浮点型、日期型等

范式二:数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。

范式三:在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是如 果存在"A → B → C"的决定关系,则C传递函数依赖于A。因此,满足第三范式的数据库表应该不存在如下依赖关系: 关键字段 → 非关键字段 x → 非关键字段y

范式是一张数据表的表结构所符合的某种设计标准的级别


展开阅读全文

没有更多推荐了,返回首页