今天继续分享 Python 相关的面试题,你已经准备好了吧!
综合篇(二),数据库和框架
关系型数据库:MySQL,Oracle,SQLServer,SQLite,DB2 非关系型数据库:MongoDB,Redis,HBase,Neo4j
建立科学的,规范的的数据库是需要满足一些规范的,以此来优化数据数据存储方式,在关系型数据库中这些规范就可以称为范式。
第一范式:当关系模式 R 的所有属性都不能在分解为更基本的数据单位时,称 R 是满足第一范式的,简记为 1NF。
关系模式R的所有属性不能再分解
第二范式:如果关系模式 R 满足第一范式,并且 R 的所有非主属性都完全依赖于 R 的每一个候选关键属性,称 R 满足第二范式,简记为 2NF。
非主属性都要依赖于每一个关键属性
三范式:设 R 是一个满足第一范式条件的关系模式,X 是 R 的任意属性集,如果 X 非传递依赖于 R 的任意一个候选关键字,称 R 满足第三范式,简记为 3NF。
数据不能存在传递关系,即每个属性都跟主键有直接关系而不是间接关系
事务(Transaction)是并发控制的基本单位。所谓的事务,它是一个操作序列,这些操作要么都执行,要么都不执行,它是一个不可分割的工作单位。 在关系数据库中,一个事务可以是一条 SQL 语句、一组 SQL 语句或整个程序。 四个属性:原子性,一致性,隔离性和持久性。
MySQL 目前主要有以下几种索引类型:
一对一关系示例: 一个学生对应一个学生档案材料,或者每个人都有唯一的身份证编号。 一对多关系示例: 一个学生只属于一个班,但是一个班级有多名学生。 多对多关系示例: 一个学生可以选择多门课,一门课也有多名学生。
触发器:触发器是一个特殊的存储过程,它是数据库在 insert、update、delete 的时候自动执行的代码块。 函数:数据库中提供了许多内置函数,还可以自定义函数,实现 sql 逻辑。 视图:视图是由查询结果形成的一张虚拟表,是表通过某种运算得到的一个投影 存储过程:把一段代码封装起来,当要执行这一段代码的时候,可以通过调用该存储过程来实现(经过第一次编译后再次调用不需要再次编译,比一个个执行 sql 语句效率高)
DML(数据操作语言)
DDL(数据定义语言)
定义主键和外键主要是为了维护关系数据库的完整性 主键是能确定一条记录的唯一标识。不能重复,不允许为空。 外键用于与另一张表关联。是能确定另一张表记录的字段,用于保持数据的一致性。
主键 | 外键 | 索引 | |
---|---|---|---|
定义 | 唯一标识一条记录,不能重复,不允许为空 | 表的外键是另一表的主键,外键可以重复,可以是空值 | 该字段没有重复值,但可以有空值 |
作用 | 用来保证数据完整性 | 用来和其他表建立联系 | 提高查询排序的速度 |
个数 | 只能有一个 | 可有多个 | 可有多个 |
mysqldump -u 用户名 -p 数据库名 > 导出的文件名
char:存储定长数据很方便,CHAR 字段上的索引效率级高,必须在括号里定义长度,可以有默认值,比如定义 char(10)。 varchar:存储变长数据,但存储效率没有 CHAR 高,必须在括号里定义长度,可以有默认值。
mysql 建立多列索引(联合索引)有最左前缀的原则,即最左优先,如:
如果有一个2列的索引(col1,col2),则已经对(col1)、(col1,col2)上建立了索引; 如果有一个3列索引(col1,col2,col3),则已经对(col1)、(col1,col2)、(col1,col2,col3)上建立了索引;
a
,b
,c
,d
),那么能命中索引的查询为 a,ab,abc,abcd,除此之外都无法命中索引读写分离,就是将数据库分为了主从库,一个主库用于写数据,多个从库完成读数据的操作,主从库之间通过某种机制进行数据的同步,是一种常见的数据库架构。
数据库水平切分,是一种常见的数据库架构,是一种通过算法,将数据库进行分割的架构。一个水平切分集群中的每个数据库,通常称为一个“分片”。每一个分片中的数据没有重合,所有分片中的数据并集组成全部数据。 水平切分分为库内分表和分库分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。
redis 默认有16个数据库,每个数据库中的数据都是隔离的,这样,在存储数据的时候,就可以指定把不同的数据存储到不同的数据库中。 且只有单机才有,如果是集群就没有数据库的概念。
RDB 持久化:是将 Reids 在内存中的数据库记录定时 dump 到磁盘上的持久化 AOF(append only file)持久化:将 Reids 的操作日志以追加的方式写入文件
通用的三种过期策略
redis 采用惰性删除+定期删除策略
限定 Redis 占用的内存,Redis 会根据自身数据淘汰策略,加载热数据到内存。 所以,计算一下所有热点数据大约占用的内存,然后设置一下 Redis 内存限制即可。
使用 redis 第三方库来操作
1import redis
2
3# 创建一个 redis 连接池
4def redis_conn_pool():
5 pool = redis.ConnectionPool(host='redis-host', port=redis-port,
6 decode_responses=True, password='redis-pwd')
7 r = redis.Redis(connection_pool=pool)
8 return r
订阅者
1if __name__ == "__main__":
2 conn = redis.Redis(host='',
3 port=12143, password='')
4
5 ps = conn.pubsub()
6 ps.subscribe('chat') # 从 chat 订阅消息
7 for item in ps.listen(): # 监听状态:有消息发布了就拿过来
8 if item['type'] == 'message':
9 print(item)
10 print(item['channel'])
11 print(item['data'])
发布者
1if __name__ == "__main__":
2 number_list = ['300033', '300032', '300031', '300030']
3 signal = ['1', '-1', '1', '-1']
4 pool = redis.ConnectionPool(host='redis-12143.c8.us-east-1-3.ec2.cloud.redislabs.com', port=12143,
5 decode_responses=True, password='pkAWNdYWfbLLfNOfxTJinm9SO16eSJFx')
6 r = redis.Redis(connection_pool=pool)
7 for i in range(len(number_list)):
8 value_new = str(number_list[i]) + ' ' + str(signal[i])
9 print(value_new)
10 r.publish("chat", value_new)
1import redis
2con = redis.Redis()
3con.keys(pattern='key*') # *代表通配符
1class Zhan:
2 def __init__(self,conn):
3 self.conn = conn
4 def push(self,val):
5 self.conn.rpush('aaa',val)
6 def pop(self):
7 return self.conn.rpop('aaa')
8
9class Dui:
10 def __init__(self,conn):
11 self.conn = conn
12 def push(self,val):
13 self.conn.rpush('bbb',val)
14 def get(self):
15 return self.conn.lpop('bbb')
16
17class Xu:
18 def __init__(self,conn):
19 self.conn = conn
20 def push(self,val,count):
21 self.conn.zadd('ccc',val,count)
22 def get(self):
23 a = self.conn.zrange('ccc', 0, 0)[0]
24 self.conn.zrem('ccc', a)
25 return a
在从服务器中配置 SLAVEOF 127.0.0.1 6380 # 主服务器 IP,端口
1def list_iter(name):
2 """
3 自定义redis列表增量迭代
4 :param name: redis中的name,即:迭代name对应的列表
5 :return: yield 返回 列表元素
6 """
7 list_count = r.llen(name)
8 for index in xrange(list_count):
9 yield r.lindex(name, index)
watch 用于在进行事务操作的最后一步也就是在执行 exec 之前对某个 key 进行监视,如果这个被监视的 key 被改动,那么事务就被取消,否则事务正常执行。
为 redis 集群设计的锁,防止多个任务同时修改数据库,其本质就是为集群中的每个主机设置一个会超时的字符串,当集群中有一半多的机器设置成功后就认为加锁成功,直至锁过期或解锁不会有第二个任务加锁成功。
超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议。HTTP 是一个客户端和服务器端请求和应答的标准。客户端是终端用户,服务器端是网站。一般由 HTTP 客户端发起一个请求,建立一个到服务器指定端口(默认是80端口)的 TCP 连接,HTTP 服务器则在那个端口监听客户端发送过来的请求,并给与响应。
WSGI:全称是 Web Server Gateway Interface,是一种描述 web server 如何与 web application 通信的规范。django,flask 等都遵循该协议。
uwsgi:是服务器和服务端应用程序的一种协议,规定了怎么把请求转发给应用程序和返回; uwsgi 是一种线路协议而不是通信协议,在此常用于在 uWSGI 服务器与其他网络服务器的数据通信。
uWSGI:是一个 Web 服务器,它实现了 WSGI 协议、uwsgi、http 等协议。Nginx 中 HttpUwsgiModule 的作用是与 uWSGI 服务器进行交换。
1xx: 信息 2xx:成功 3xx:重定向 4xx:客户端错误 5xx:服务器错误
GET,POST,PUT,DELETE,PATCH 等
响应式布局是 Ethan Marcotte 在2010年5月份提出的一个概念,简而言之,就是一个网站能够兼容多个终端——而不是为每个终端做一个特定的版本。
AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。 AJAX = 异步 JavaScript 和 XML
1$(function(){
2 $('#send').click(function(){
3 $.ajax({
4 type: "GET",
5 url: "test.json",
6 data: {username:$("#username").val(), content:$("#content").val()},
7 dataType: "json",
8 success: function(data){
9 $('#resText').empty(); //清空resText里面的所有内容
10 var html = '';
11 $.each(data, function(commentIndex, comment){
12 html += '<div class="comment"><h6>' + comment['username']
13 + ':</h6><p class="para"' + comment['content']
14 + '</p></div>';
15 });
16 $('#resText').html(html);
17 }
18 });
19 });
20});
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
如果两个页面的协议,端口(如果有指定)和主机都相同,则两个页面具有相同的源。我们也可以把它称为“协议/主机/端口 tuple”,或简单地叫做“tuple". ("tuple" ,“元”,是指一些事物组合在一起形成一个整体,比如(1,2)叫二元,(1,2,3)叫三元)
CORS 全称是跨域资源共享(Cross-Origin Resource Sharing),是一种 AJAX 跨域请求资源的方式,支持现代浏览器。
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
轮询
1var xhr = new XMLHttpRequest();
2 setInterval(function(){
3 xhr.open('GET','/user');
4 xhr.onreadystatechange = function(){
5
6 };
7 xhr.send();
8 },1000)
长轮询
1 function ajax(){
2 var xhr = new XMLHttpRequest();
3 xhr.open('GET','/user');
4 xhr.onreadystatechange = function(){
5 ajax();
6 };
7 xhr.send();
8 }
所谓 MVC 就是把 web 应用分为模型(M),控制器(C),视图(V)三层,他们之间以一种插件似的,松耦合的方式连接在一起。 模型负责业务对象与数据库的对象(ORM),视图负责与用户的交互(页面),控制器(C)接受用户的输入调用模型和视图完成用户的请求。
Django 中的 MTV 模式:Model(模型):负责业务对象与数据库的对象(ORM),Template(模版):负责如何把页面展示给用户,View(视图):负责业务逻辑,并在适当的时候调用 Model 和 Template,本质上与 MVC 相同。
接口幂等性就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了副作用。
简洁,轻巧,扩展性强,自由度高。
ORM 的全称是 Object Relational Mapping,即对象关系映射。它的实现思想就是将关系数据库中表的数据映射成为对象,以对象的形式展现,这样开发人员就可以把对数据库的操作转化为对这些对象的操作。
PV:是(page view)访问量,页面浏览量或点击量,衡量网站用户访问的网页数量。在一定统计周期内用户每打开或刷新一个页面就记录1次,多次打开或刷新同一页面则浏览量累计。 UV:是(Unique Visitor)独立访客,统计一段时间内访问某站点的用户数(以cookie为依据)。
supervisor 管理进程,是通过 fork/exec 的方式将这些被管理的进程当作 supervisor 的子进程来启动,所以我们只需要将要管理进程的可执行文件的路径添加到 supervisor 的配置文件中即可。
优点:
缺点:
1from django.db import connection
2cursor = connection.cursor()
3cursor.execute("SELECT DATE_FORMAT(create_time, '%Y-%m') FROM blog_article;")
4ret = cursor.fetchall()
5print(ret)
cookie 是保存在浏览器端的键值对,可以用来做用户认证。
sesseion 是将用户的会话信息保存在服务端,key 值是随机产生的字符串,value 值是 session 的内容,依赖于 cookie 将每个用户的随机字符串保存到用户浏览器中。
BeautifulSoup 库是解析、遍历、维护“标签树”的功能库。
1url = "http://www.baidu.com/"
2request = requests.get(url)
3html = request.content
4soup = BeautifulSoup(html, "html.parser", from_encoding="utf-8")
Selenium 是模拟操作浏览器的库,可以根据我们的指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏,或者判断网站上某些动作是否发生等。
1from selenium import webdriver
2browser = webdriver.Chrome()
3browser.get('https://www.taobao.com')
4print(browser.page_source) # browser.page_source 是获取网页的全部 html
5browser.close()