面试题2

'''第一题。MySQL有哪些存储引擎,优化MySQL数据库的方法有哪些'''
'''
数据库存储引擎是数据库底层的软件组织,数据库管理系统(DBMS)使用数据引擎进行创建,查询,更新,删除。
不同存储引擎提供不同的存储机制,索引技巧,锁定水平等功能,使用不同的存储引擎,还可以获得特定的功能。
现在许多不同的数据库管理系统都支持多种不同的数据引擎。MySQL的核心就是存储引擎

1.InnoDB存储引擎:InnoDB是事务性数据库的首选引擎
    InnoDB的特性有:
        1.InnoDB给MySQL提供了具有提交,回滚和崩溃恢复能力的食物安全(ACID)存储引擎
        2.InnoDB是为处理巨大数据量的最大性能设计。它的CPU效率可能是任何其他基于其他磁盘的关系型数据库引擎所不能匹敌的。
        3.InnoDB存储引擎完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。
        4.InnoDB支持外键的完整性约束,存储数据时,每张表都按主键的顺序存放
        5.InnoDB被用在众多需要高性能的大型数据库站点上
2.MyISAM存储引擎:MyISAM是基于ISAM存储引擎,并对其进行扩展。它在Web,数据仓库和其他应用环境下最常用的存储引擎之一。
    MyISAM的特性有:
        1、大文件(达到63位文件长度)在支持大文件的文件系统和操作系统上被支持
        2、当把删除和更新及插入操作混合使用的时候,动态尺寸的行产生更少碎片。这要通过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块自动完成
        3、每个MyISAM表最大索引数是64,这可以通过重新编译来改变。每个索引最大的列数是16
        4、最大的键长度是1000字节,这也可以通过编译来改变,对于键长度超过250字节的情况,一个超过1024字节的键将被用上
        5、BLOB和TEXT列可以被索引
        6、NULL被允许在索引的列中,这个值占每个键的0~1个字节
        7、所有数字键值以高字节优先被存储以允许一个更高的索引压缩
        8、每个MyISAM类型的表都有一个AUTO_INCREMENT的内部列,当INSERT和UPDATE操作的时候该列被更新,同时AUTO_INCREMENT列将被刷新。所以说,MyISAM类型表的AUTO_INCREMENT列更新比InnoDB类型的AUTO_INCREMENT更快
        9、可以把数据文件和索引文件放在不同目录
        10、每个字符列可以有不同的字符集
        11、有VARCHAR的表可以固定或动态记录长度
        12、VARCHAR和CHAR列可以多达64KB
        使用MyISAM引擎创建数据库,将产生3个文件。文件的名字以表名字开始,扩展名之处文件类型:frm文件存储表定义、数据文件的扩展名为.MYD(MYData)、索引文件的扩展名时.MYI(MYIndex)
3.MEMORY存储引擎:MEMORY存储引擎将表中的数据存储到内存中,未查询和引用其他表数据提供快速访问。
    MEMORY的主要特性有:
        1、MEMORY表的每个表可以有多达32个索引,每个索引16列,以及500字节的最大键长度
        2、MEMORY存储引擎执行HASH和BTREE缩影
        3、可以在一个MEMORY表中有非唯一键值
        4、MEMORY表使用一个固定的记录长度格式
        5、MEMORY不支持BLOB或TEXT列
        6、MEMORY支持AUTO_INCREMENT列和对可包含NULL值的列的索引
        7、MEMORY表在所由客户端之间共享(就像其他任何非TEMPORARY表)
        8、MEMORY表内存被存储在内存中,内存是MEMORY表和服务器在查询处理时的空闲中,创建的内部表共享
        9、当不再需要MEMORY表的内容时,要释放被MEMORY表使用的内存,应该执行DELETE FROM或TRUNCATE TABLE,或者删除整个表(使用DROP TABLE)
4.MERGE存储引擎:
'''
'''
优化MySQL数据库的方法:
    1.创建索引:索引是提高数据库性能的常用方法,它可以令数据库服务器比没有索引快得多的速度检索待定行
    2.选取最适用的字段属性:为了获得好的性能,表中字段的宽度尽量小,将字段设置为不为空,也可以提高数据库的查询效率,因为这样将来执行查询时,数据库不用再比较NUll
    3.使用连接(JOIN)来代替子查询:
    4.使用联合索引(UNION)来代替手动创建的临时表
    5.事务:
    6.锁定表:
    7.使用外键
    8.优化查询语句:
        a.首先,最好是在相同的字段间进行比较操作 
        b.其次,在建有索引的字段上尽量不要使用函数操作
        c.在搜索字符型字段时,尽量不要用LIKE关键字和通配符,这种做法虽然简单,但却是以牺牲系统性能为代价的
        d.应避免查询中让MySQL进行自动类型转换,因为转换的过程可能会使索引不起作用
    
'''
'''第二题:session与cookie的作用与区别'''
'''
session:
    由于HTTP是无状态协议,所以服务端用于记录用户状态时,就需要某种机制来具体识别用户,这个机制就是session
    在服务端保存session的方法有很多,内存,文件,数据库,大型网站一般放在内存中
cookie:
    服务端识别特定的用户,每次HTTP请求时,客户端都会发送相应的cookie信息到服务器。
    实际上大多数应用都是用cookie来实现session跟踪的,第一次创建session时,服务端
    会在HTTP协议中告诉客户端,需要在cookie里面记录一个sessionID,以后每次请求把这
    个ID发送到服务端,服务端据此来识别用户
'''
'''
区别:
    1.session在服务端,cookie在客户端
    2.session被默认保存在服务器的一个临时文件里,也可以更改至数据库,或者是内存中,cookie保存在HTML的请求头中
    3.session运行依赖session ID 而session ID存放于cookie中,也就说,浏览器禁用cookie,session也会失效
    (也可以通过其他方式实现,比如在URL中传递sessionID)
    4.用户验证一般会使用session
'''


'''第三题:web开发中如何防止sql注入'''
'''
sql注入:
    所谓sql注入,就是通过把sql命令插入到web表单提交,或输入域名或页面请求的查询字符串,
    最终达到欺骗服务器执行恶意的sql命令
原理:
    sql注入攻击是通过构建特殊的输入作为参数传入web应用,而这些输入大都是sql语法的一些组合,
    通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致的过滤用户的输入数据,
    致使非法数据侵入系统
原因:
    sql注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;
    后者主要是由于程序员对输入未进行细致的过滤,从而执行非法的数据查询。基于此,
    sql注入产生原因主要表现在以下几个方面:
        0.未经检查或未经充分的检查用户的输入数据,意外变成代码被执行
        1.不当的类型处理
        2.不安全的数据库配置
        3.不合理的查询集处理
        4.不当的错误处理
        5.转义字符处理不合适
        6.多个提交处理不当
方法:
    1.参数化查询或者词法分析
    2.避免用户提交的数据变成代码被执行
    3.对用户输入的数据进行校验,可以通过正则表达式,或者限制长度;对单引号和双下划线进行转换
    4.不要使用动态拼接sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取
    5.不要把机密信息直接存放,加密或者hash掉密码等敏感信息
'''


'''第四题.编写快速排序或者冒泡排序'''

def timer(func):
    def inner(*args,**kwargs):
        start = time.time()

        func(*args)
        end = time.time()
        print('%s代码运行时间为%s'%(func,(end-start)))
    return inner
'''
冒泡排序:
    它重复的走访需要排序的数列,一次比较两个元素,如果它们顺序错误就把它们交换过来。
    走访数列的工作是重复进行直到没有需要在继续交换,也就是说,该数列已经排序完成。
'''
@timer
def bubble_sort(list1):
    '''冒泡排列'''
    count=len(list1)
    for i in range(count):
        for j in range(i+1,count):
            if list1[i]>list1[j]:
                list1[i],list1[j] = list1[j],list1[i]
    return list1
'''
插入排序:
    插入排序的基本操作就是将一个数据插入到已经排好的有序数据中,从而得到一个新的、
    个数加一的有序数据,算法适用于少量数据排列,时间复杂度为O(n^2)。是稳定的排序方法。
    插入算法要把排序的数组分成两个部分,第一部分包含数组的所有元素,但将最后一个元素除外,
    (让数组多一个空间才有插入的位置),第二部分就只包括插入元素。在第一部分插入完成后,
    再将这个最后元素插入到已排好序的第一部分中。
'''
@timer
def inset_sort(list2):
    '''插入排序'''
    count=len(list2)
    for i in range(1,count):
        value=list2[i]
        j=i-1
        while j>=0:
            if list2[j]>value:
                list2[j+1]=list2[j]
                list2[j]=value
            j-=1
    return list2

'''
直接选择排序:
    第一趟,在待排序记录中选择最小的,他将于i0交换,第二趟,在其余数中选择最小的’
    他将于i2交换,以此类推
'''
@timer
def select_sort(list3):
    '''直接选择排列法'''
    count=len(list3)
    for i in range(count):
        min=i
        for j in range(i+1,count):
            if list3[min]>list3[j]:
                min=j
        list3[min],list3[i]=list3[i],list3[min]
    return list3

if __name__ == '__main__':
    import random,time
    li=[i for i in range(10000)]
    random.shuffle(li)
    print('排序前', li)
    '''冒泡排序'''

    # bubble_sort(li)#<function bubble_sort at 0x000000000295C8C8>代码运行时间为5.76800012588501
    # inset_sort(li)#<function inset_sort at 0x000000000292C840>代码运行时间为7.107000112533569
    # select_sort(li)#<function select_sort at 0x000000000295C620>代码运行时间为3.4589998722076416



    print('排序后',li)
    print(len(li))
原文地址:https://www.cnblogs.com/ldq1996/p/8039673.html