• 数据分析面试题(2023.09.08)


    数据分析流程

    总体分为四层:需求层、数据层、分析层和结论层

    一、统计学问题

    1、贝叶斯公式复述并解释应用场景

    • 公式:P(A|B)= P(B|A)*P(A) / P(B)
    • 应用场景:如搜索query纠错,设A为正确的词,B为输入的词,那么:

        a. P(A|B)表示输入词B实际为A的概率

        b. P(B|A)表示词A错输为B的概率,可以根据AB的相似度计算(如编辑距离)

        c. P(A)是词A出现的频率,统计获得

        d. P(B)对于所有候选的A都一样,所以可以省去
       

    • 朴素贝叶斯是在已知一些先验概率的情况下,由果索因的一种方法。朴素的意思是假设了事件相互独立。

    2、参数估计

    参数估计是指根据从总体中抽取的样本估计总体分布中包含的未知参数的方法。它是统计推断的一种基本形式,是数理统计学的一个重要分支,分为点估计和区间估计两部分。

    • 点估计:依据样本估计总体分布中所含的未知参数或未知参数的函数。 

    •  区间估计(置信区间估计):依据抽取的样本,根据一定的正确度与精确度要求,构造出适当的区间,作为总体分布的未知参数或参数的函数的真值所在范围的估计。例如人们常说的由百分之多少的把握保证某值在某个范围内,即用区间估计的最简单的应用。 

    3、极大似然估计

     极大似然估计是利用已知的样本结果,反推最有可能(最大概率)导致这样结果的参数值。

    4、假设检验

    参数估计和假设检验是统计推断的两个组成部分,它们都是利用样本对总体进行某种推断,但推断的角度不同。

    • 参数估计讨论的是用样本估计总体参数的方法,总体参数μ在估计前是未知的。
    • 假设检验,是先对μ的值提出一个假设额,然后利用样本信息去检验这个假设是否成立。 

    5、P值是什么? 

    P值是用来判定假设检验结果的一个参数,也可以根据不同的分布使用分布的拒绝域进行比较。

    P值就是当原假设为真时所得到的样本观察结果或更极端结果出现的概率。如果P值很小,说明原假设情况的发生的概率很凶啊,而如果出现了,根据小概率原理,我们就有理由拒绝原假设。P值越小,我们拒绝原假设的理由越充分。总之,P值越小,表明结果越显著。但是检验的结果究竟时“显著的”“中度显著的”还是“高度显著的”需要我们自己根据P值的大小和实际问题来解决。

    6、置信度和置信区间

    • 置信区间:我们所计算出的变量存在范围
    • 置信度:就是我们对于这个数值存在于我们计算出的这个范围的可信程度。
    • 举例:①有95%的把握,真正的数值在我们所计算的范围里。95%是置信水平,而计算出的范围,就是置信区间。②如果置信度为95%,则抽取100个样本来估计总体的均值,由100个样本所构造的100个区间中,约有95个区间包含总体均值。

    7、协方差和相关系数的区别和联系

    • 协方差:协方差表示的是两个变量的总体误差,这与只表示一个变量误差的方差不同。如果两个变量的变化趋势一致,也就是说如果其中一个大于自身期望值,另外一个也大于自身的期望值,那么两个变量之间的协方差就是正值,如果两个变量的变化趋势相反,即其中一个大于自身的期望值,另外一个却小于自身的期望值,那么两个变量之间的协方差就是负值。
    • 相关系数:研究变量之间线性相关程度的量,取值范围是[-1,1],相关系数也可以看成协方差--一种剔除了两个变量量纲影响、标准化后的特殊协方差。

    8、中心极限定理

    • 定义:①任何一个样本的平均值将会约等于其所在总体的平均值;②不管总体是什么分布,任意一个总体的样本平均值都会围绕在总体的平均值周围,并且呈正态分布。
    • 作用:①在没有办法得到总体全部数据的情况下,我们可以用样本来估计总体;②根据总体的平均值和标准差,判断某个样本是否属于总体。

    二、概率问题

    1、54张扑克牌,分成2份,求着2份都有2张A的概率。

    M表示这两个牌堆各有2个A的情况:M=4(25!25!)

    N表示两个牌堆完全随机的情况:N=27!27!

    概率为:M/N=926/53*17

    2、男生点击率增加,女生点击率增加,总体为何减少?

    因为男女的点击率可能有较大的差异,同时低点击率的群体的占比增大。

    如原来男性20人,点击1人;女性100人,点击99人,总点击率100/120

    现在男性100人,点击6人;女性20人,点击20人,总点击率26/120

    三、数据库

    1、什么是数据库,数据库管理系统,数据库系统,数据库管理员?

    • 数据库:数据库DataBase就是信息的集合或者说数据库是由数据库管理系统管理的数据的集合。
    • 数据库管理系统:数据库管理系统是一种操纵和管理数据库的大型软件,通常用于建立、使用和维护数据库。
    • 数据库系统:数据库系统通常由软件、数据库和数据库管理员组成。
    • 数据库管理员:数据库管理员负责全面管理和控制数据库系统。

    2、什么是元组、码、候选码、主码、外码、主属性、非主属性

    • 元组:元组是关系数据库中的基本概念,关系是一张表,表中的每行(即数据库中的每条记录)就是一个元组,每列是一个属性,在二维表中,元组也称为行。
    • 码:码就是能唯一识别实体的属性,对应表中的列。
    • 候选码:若关系中的某一属性或属性组的值能唯一识别一个元组,而其任何子集都不能再表示,则称该属性组为候选码。在学生实体中,“学号”是能唯一的区分学生实体的,同时又假设“姓名”、“班级”的属性组合足以区分学生实体,那么{学号}和{姓名,班级}都是候选码。
    • 主码:主码也叫主键,主码是从候选码中选出来的,一个实体集中只能有一个主码,但可以有多个候选码。
    • 外码:外码也叫外键,如果关系中的一个属性是另外一个关系的主码,则这个属性是外码。
    • 主属性:候选码中出现过的属性称为主属性,比如工人(工号,身份证号,姓名,性别,部门)。显然工号和身份证号都能够唯一标示这个关系,所以都是候选码。工号、身份证号这两个属性就是主属性。如果主码是一个属性组,那么属性组中的属性都是主属性。
    • 非主属性:不包含在任何一个候选码中的属性称为非主属性。比如在关系——学生(学号,姓名,年龄,性别,班级)中,主码是“学号”,那么其他的“姓名”、“年龄”、“性别”、“班级”就都可以称为非主属性。

    3、主键和外键有什么区别?

    • 主键:主键用于唯一表示一个元组,不能有重复,不允许有空,一个表只能有一个主键。
    • 外键:外键用来和其他表建立联系用,外键是另一表的主键,外键是可以有重复的,可以是空值,一个表可以有多个外键。

    4、数据库的范式 

    • 第一范式(1NF):属性(回应表中的字段)不能再被分割,也就是这个字段只能是一个值,不能再被分为多个其他字段了(原子性)。1NF是所有关系型数据库的最基本要求,也就是说关系型数据库中创建的表一定满足第一范式。
    • 第二范式(2NF):2NF在1NF的基础之上,消除了非主属性对码的部分函数依赖。第二范式在第一范式的基础上增加了一个列,这个列称为主键,非主属性都依赖于主键。
    • 第三范式(3NF):3NF在2NF的基础之上,消除了非主属性对码的传递依赖。解决了数据冗余过大,插入异常,修改异常,删除异常的问题。比如在关系R(学号 ,姓名, 系名,系主任)中,学号 → 系名,系名 → 系主任,所以存在非主属性系主任对于学号的传递函数依赖,所以该表的设计,不符合3NF的要求。
    • 总结:1NF:属性不可再分。2NF:1NF的基础之上,消除了非主属性对于码的部分函数依赖。3NF:3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖 。

    5、什么是函数依赖?部分函数依赖?完全函数依赖?传递函数依赖?

    • 函数依赖(functional dependency): 若在一张表中,在属性(属性组)X的值确定的情况下,必定能确定属性Y的值,那么就可以说Y函数依赖于X,写作X → Y。
    • 部分函数依赖:如果X → Y,并且存在X的一个真子集X0,使得X0→ Y,则称Y对X部分函数依赖。比如学生基本信息表R中(学号,身份证号,姓名)当然学号属性取值是唯一的,在R关系中,(学号,身份证号)->(姓名),(学号)->(姓名),(身份证号)->(姓名);所以姓名部分函数依赖与(学号,身份证号)。
    • 完全函数依赖(Full functional dependency) :在一个关系中,若某个非主属性数据依赖于全部关键字称之为完全函数依赖。比如学生基本信息表R(学号,班级,姓名)假设不同的班级学号有相同的,班级内学号不能相同,在R关系中,(学号,班级)->(姓名),但是(学号)->(姓名)不成立,(班级)->(姓名)不成立,所以姓名完全函数依赖于(学号,班级)。
    • 传递函数依赖(transitive functional dependency) :在关系模式R(U)中,设X,Y,Z是U的不同的属性子集,如果X确定Y、Y确定Z,且有X不包含Y,Y不确定X,(X∪Y)∩Z=空集合,则称Z传递函数依赖于X。传递函数依赖会导致数据冗余和异常。传递函数依赖的Y和Z子集往往同属于某一个事物,因此可将其合并放到一个表中。比如在关系R(学号 ,姓名, 系名,系主任)中,学号 → 系名,系名 → 系主任,所以存在非主属性系主任对于学号的传递函数依赖。

    6、什么是存储过程?

    我们可以把存储过程看成是一些SQL语句的集合,中间加了点逻辑控制语句。存储过程在业务比较复杂的时候非常实用,比如很多时候我们完成一个操作可能需要写一大串SQL语句,这时候我们可以写有一个存储过程,这样也方便了我们下一次的调用。存储过程一旦调试完成通过后就能稳定运行,另外,使用存储过程单纯比SQL语句执行要快,因为存储过程是预编译过的。

    但部分公司存储过程应用不多,因为存储过程难以调试和扩展,而且没有移植性,还会消耗数据库资源。

    7、drop 、delete和truncate区别?

    • drop(丢弃数据):drop table(表名),直接删除表。
    • truncate(清空数据):truncate table(表名),只删除表中的数据,再插入数据的时候自增长id又从1开始,在清空表中数据的时候使用。
    • delete(删除数据):delete from 表名 where 列名=值,删除某一列的数据,如果不加where子句和truncate table表名作用类似。
    • 总结:truncate和不带where子句的delete、以及drop都会删除表内的数据,但是truncate和delete只删除数据不删除表的结构(定义),执行drop语句,此表的结构也会删除,也就是执行drop以后对应的表不复存在。
    • truncate和drop属于DDL(数据定义语言)语句,操作立即生效,原数据不放在rollback segment中,不能回滚,操作不触发trigger。而delete语句是DML(数据库操作语言)语句,这和操作会放到rollback segment中,事务提交之后才生效。
    • 执行速度:drop>truncate>delete

    8、DML语句和DDL语句的区别。

    • DML 是数据库操作语言(Data Manipulation Language)的缩写,是指对数据库中表记录的操作,主要包括插入(insert)、更新(update)、删除(delete)和查询(select),是开发人员日常使用最频繁的操作。
    • DDL(Data Definition Language)是数据定义语言的缩写,简单来说,就是对数据库内部的对象进行创建、删除、修改的操作语句。它和DML语言的最大区别是DML只是对表内部数据的操作,而不涉及表的定义、结构的修改,更不会涉及到其他对象。DDL语句更多的被数据库管理员(DBA)所使用,一般的开发人员很少使用。

    9、数据库设计通常分为哪几步?

    • 需求分析:分析用户的需求,包括数据、功能和性能需求。
    • 概念结构设计:主要采用E-R模型进行设计,包括画E-R图。
    • 逻辑结构设计:通过将E-R图转换为表,实现从E-R模型到关系模型的转换。
    • 物理结构设计:主要是为所设计的数据库选择合适的存储结构和存取路径。
    • 数据库实施:包括编程、测试和试运行。
    • 数据库运行和维护:系统的运行与数据库的日常维护。

    10、事务的ACID特性是什么?★

    • 原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成、要么完全不起作用。
    • 一致性:执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的。
    • 隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的。
    • 持久性:一个事务被提交之后。它对数据库的数据的改变是持久的。即使数据库发生故障也不应该对其有任何影响。

    11、并发事务带来哪些问题?

    在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对统一数据进行操作)并发虽然是必须的,但可能会导致以下的问题:

    • 脏读(Dirty read):当一个事务正在访问数据并且对这个数据进行了修改,而这种修改还没有提及到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据脏数据所作的操作可能是不正确的。(其他事务读取了修改以前的数据,涉及操作为修改-查询)
    • 丢失修改(Lost to modify):指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。(两个事务同时修改,后一个事务修改结果覆盖了之前修改的结果,涉及的操作为修改-修改)
    • 不可重复读(Unrepeatableread):指在一个事务内多次读同一个数据,在这个事务还没结束的时候,另一个事务也访问了该数据并修改,导致第一个事务两次读取的数据不一样,称为不可重复读。(第一个事务多次读的间隙,第二个事务修改,导致第一个事务不可重复读,涉及的操作有查询-修改-查询)
    • 幻读(Phantom read):幻读和不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务就会发现多了一些原本不存在的记录,就好像存在了幻觉一样,所以称为幻读。(第一个事务读取过程中,第二个事务增加或删除,导致第一个事务读取结果不一致,涉及的操作有查询-增加/删除-查询)

    12、不可重复读和幻读有什么区别?

    不可重复读的重点是修改,幻读的重点在于新增或者删除。

    13、事务的隔离级别有哪些?MySQL的默认隔离级别是?

    SQL标准定义了四个隔离级别:

    • Read-uncommitted(读取未提交):最低的隔离级别,允许读取尚未提交的数据变更,可能导致脏读、不可重复读和幻读)
    • Read-committed(读取已提交):允许读取并发事务已经提交的数据,可以阻止脏读。但不可重复读和幻读仍有可能发生。
    • Repeatable-read(可重复读):对同一字段的多次读取结果都是一致的,除非数据是被本身事务所修改,可以阻止脏读和不可重复读,幻读仍有可能发生。
    • Serializable(可串行化):最高的隔离级别,完全服从ACID的隔离级别,所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,可以阻止脏读、不可重复读以及幻读。
    • mySQL的默认隔离级别是可重复读。

    14、乐观锁和悲观锁的区别

    • 悲观锁:总是假设最坏的情况,每次去拿数据都认为别人会修改,所以每次在拿数据时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其他线程阻塞,用完后再把资源转让给其他线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁;读锁,写锁等,都是在操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
    • 乐观锁:总是假设最好的情况,每次去拿数据时都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁使用多读的应用类型,这样可以提高吞吐量。想数据中提供的类似write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的
    • 两种锁的使用场景:乐观锁适用于多读场景;悲观锁适用于多写场景。

    15、乐观锁的两种实现方式。

    • 版本号机制:一般在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值加一,当线程A要更新数据时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中version值相等时才更新,否则重试更新操作,直到更新成功。(提交版本必须大于记录版本才能执行更新)

      举一个简单的例子: 假设数据库中帐户信息表中有一个 version 字段,当前值为 1 ;而当前帐户余额字段( balance )为 $100 。操作员 A 此时将其读出( version=1 ),并从其帐户余额中扣除 (50(100-$50 )。在操作员 A 操作的过程中,操作员B 也读入此用户信息( version=1 ),并从其帐户余额中扣除 (20(100-$20 )。操作员 A 完成了修改工作,将数据版本号加一( version=2 ),连同帐户扣除后余额( balance=$50 ),提交至数据库更新,此时由于提交数据版本大于数据库记录当前版本,数据被更新,数据库记录 version 更新为 2 。操作员 B 完成了操作,也将版本号加一( version=2 )试图向数据库提交数据( balance=$80 ),但此时比对数据库记录版本时发现,操作员 B 提交的数据版本号为 2 ,数据库记录当前版本也为 2 ,不满足 “ 提交版本必须大于记录当前版本才能执行更新 “ 的乐观锁策略,因此,操作员 B 的提交被驳回。这样,就避免了操作员 B 用基于 version=1 的旧数据修改的结果覆盖操作员A 的操作结果的可能。

    • CAS算法:compare和swap(比较与交换),是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步。也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization),CAS算法涉及三个操作数①需要读写的内存值V,②进行比较的值A,③拟写入的新值B。④当且仅当V的值等于A时,CAS通过原子方式用新值B来更新V的值,否则不会执行任何操作(比较和替换是一个原子操作),一般情况下是一个自旋操作,即不断重试。

    16、乐观锁的缺点。

    • ABA问题:如果一个变量V初次读取时是A值,并且在准备赋值时候检查到它仍然为A,那我们就能说明它的值没有被其他线程修改过吗?很明显不能,因为这段时间,它的值有可能被改为其他值,然后又改回A,那CAS操作就误以为它从来没有被修改过。这个问题被称为CAS操作的 "ABA"问题。JDK 1.5 以后的 AtomicStampedReference 类就提供了此种能力,其中的 compareAndSet 方法就是首先检查当前引用是否等于预期引用,并且当前标志是否等于预期标志,如果全部相等,则以原子方式将该引用和该标志的值设置为给定的更新值。
    • 循环时间开销大:自旋CAS(也就是不成功就一直循环执行直到成功),如果长时间不成功,会给CPU带来非常大的执行开销,如果JVM能支持处理器提供的pause指令那么效率会有一定的提升,pause指令有两个作用,第一它可以延迟流水线执行指令(de-pipeline),使CPU不会消耗过多的执行资源,延迟的时间取决于具体实现的版本,在一些处理器上延迟时间是零。第二它可以避免在退出循环的时候因内存顺序冲突(memory order violation)而引起CPU流水线被清空(CPU pipeline flush),从而提高CPU的执行效率。
    • 只能保证一个共享变量的原子操作:CAS只对单个共享变量有效,当擦欧总涉及跨多个共享变量时CAS无效。但是从 JDK 1.5开始,提供了AtomicReference类来保证引用对象之间的原子性,你可以把多个变量放在一个对象里来进行 CAS 操作.所以我们可以使用锁或者利用AtomicReference类把多个共享变量合并成一个共享变量来操作。

    17、什么是数据库索引?

    • 数据库索引:是数据库管理系统中的一个排序的数据结构,以协助快速查询、更新数据库表中数据。
    • 实现:索引的实现通常使用B树和B+树,加速了数据访问,因为存储引擎不会再去扫描整张表得到需要的数据;相反,它从根节点开始,根节点保存了子节点的指针,存储引擎会根据指针快速寻找数据。

    上图显示了一种索引方式。左边是数据库中的数据表,有col1和col2两个字段,一共有15条记录;右边是以col2列为索引列的B_TREE索引,每个结点包含索引的建值和对应数据表地址的指针,这样就可以通过B_TREE在O(logn)的时间复杂度内获取相应的数据,这样明显加快了检索速度。为表设置索引要付出代价,一是增加了数据库的存储过程,二是在插入和修改数据时要花费较多的时间(因为索引也要随之变动)。

    18、索引的优缺点?

    • 优点:①创建索引可以大大提高系统的性能;②通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。③可以大大提升数据库的检索速度,这是创建索引最主要的原因;③可以加速表和表之间的连接,特别是在实现数据的参考完整性方面有特别有意义;④在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间;⑤通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。
    • 缺点:①创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。②索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么所需的空间就会更大。③当对表中的数据进行增加,删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

    19、一般来说,需要在哪些列上创建索引?

    • 在经常需要搜索的列上,可以加快搜索的速度。
    • 在作为主键的列上,强制该列的唯一性和组织表中数据的排列结构。
    • 在经常用在连接的列上,这些列主要是一些外键,可以加快连接的速度。
    • 在经常需要根据范围检索的列上创建索引,因为索引已经排序,其指定的范围是连续的。
    • 在经常需要排序的列上创建索引,因为索引已经排序,这样查询可以利用索引的排序,加快排序的查询时间。
    • 在经常使用where子句中的列上面创建索引,加快条件判断的速度。

    20、一般来说,那些列上不应该创建索引?

    • 在查询中很少使用或者参考的列不应该创建索引。
    • 对于很少数据值的列也不应该增加索引。
    • 对于定义text,image,和bit数据类型的列不应该增加索引,因为这些列数据量要么相当大,要么取值很小。
    • 当修改性能远远小于检索性能时,不应该创建索引。修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

    21、数据库设计器中创建三种索引:唯一索引、主键索引和聚集索引。

    • 唯一索引:不允许其中任何两行具有相同索引值的索引。当现有的数据中存在重复的键值,大多数数据库不允许将新创建的唯一索引与表一起保存。数据库还可能防止添加将在表中创建重复键值的新数据。例如,如果在 employee 表中职员的姓(lname)上创建了唯一索引,则任何两个员工都不能同姓。
    • 主键索引:数据库表中经常有一列或几列组合,其值唯一标识表中的每一行。该列称为表的主键。在数据库关系图中为表定义主键将自动创建主键索引,主键索引是唯一索引的特定类型。该索引要求主键中的每个值都唯一。当在查询中使用主键索引时,它还允许对数据的快速访问。
    • 聚集索引:在聚集索引中,表中行的物理顺序与键值的逻辑(索引)顺序相同,一个表只能包含一个聚集索引。如果某索引不是聚集索引,则表中行的物理顺序与键值的逻辑顺序不匹配。与非聚集索引相比,聚集索引通常提供更快的数据访问速度。

    22、MyISAM和InnoDB两个存储引擎的索引

    • MyISAM索引实现:使用B+树作为索引结构,叶子节点的data域存放的数据记录的地址。下图是MyISAM索引的原理图,设表一共有三列,假设我们以COL1作为主键,则下图是一个MyISAM表的主索引(Primary key)示意,可以看出MyISAM的索引文件仅仅保存数据记录的地址

    • 辅助索引:在MyISAM中,主索引和辅助索引(Secondary key)在结构上没有任何区别,只是主索引要求Key是唯一的,而辅助索引的key可以重复。如果我们在COL2上建立一个辅助索引,而此索引的结构如下图所示,同样是一棵B+树,data域保存数据记录的地址。因此MyISAM 中索引检索的算法为首先按照 B+Tree 搜索算法搜索索引,如果指定的key存在,则取出其data域的值,然后以data域的值为地址,读取相应数据记录:
    • MyISAM 的索引方式也叫做“非聚集索引”,之所以这么称呼是为了与 InnoDB的聚集索引区分。
    • InnoDB索引:也使用B+树作为索引结构,与MyISAM的第一个重大区别是InnoDB的数据文件本身就是索引文件。从上文知道 ,MyISAM 索引文件和数据文件是分离的,索引文件仅保存数据记录的地址。而在InnoDB中,表数据文件本身就是按 B+Tree 组织的一个索引结构,这颗树的叶子节点data域保存了完整的数据记录。这个索引的key是数据表的主键,,因此InnoDB表数据文件本身就是主索引。这种索引叫做聚集索引,因为InnoDB数据文件本身要按主键聚集。
    • InnoDB要求表必须有主键 (MyISAM 可以没有),如果没有显式指定,则 MySQL系统会自动选择一个可以唯一标识数据记录的列作为主键,如果不存在这种列,则MySQL 自动为 InnoDB 表生成一个隐含字段作为主键,类型为长整形。同时,请尽量在 InnoDB 上采用自增字段做表的主键。因为 InnoDB 数据文件本身是一棵B+Tree,非单调的主键会造成在插入新记录时数据文件为了维持 B+Tree 的特性而频繁的分裂调整,十分低效,而使用自增字段作为主键则是一个很好的选择。如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页。这样就会形成一个紧凑的索引结构,近似顺序填满。由于每次插入时也不需要移动已有数据,因此效率很高,也不会增加很多开销在维护索引上。如下图所示:
    • 第二个与  MyISAM 索引的不同是 InnoDB 的辅助索引 data 域存储相应记录主键的值而不是地址。换句话说,InnoDB 的所有辅助索引都引用主键作为 data 域。例如下图为定义在 Col3 上的一个辅助索引:

    23、B树和B+树的区别

    • B树是一棵多路平衡查找树。每个节点最多有m-1个关键字(可以存有的键值对);根节点最少可以只有1个关键字,非根节点至少有m/2个关键字。每个节点的关键字都按照从小到大的顺序排列,每个关键字的左子树中的所有关键字都小于它,而右子树中的左右关键字都大于它。所有叶子节点都位于同一层,或者说根节点到每个叶子节点的长度都相同。每个节点都存有索引和数据。也就是对应的key和value。所以根节点的关键字范围:1<=k<=m-1,非根节点的关键字数量范围m/2<=k<=m-1。另外描述一棵B树时需要指定它的阶数,阶数表示了一个节点最多有多少个孩子节点,一般用字母m表示阶数。
    • B+树与B树的相同点:①根节点至少一个元素;②非根节点元素范围:m/2<=k<=m-1。
    • B+树与B树的不同点:①B+树有两种类型的节点:内部节点(也称为索引节点)和叶子节点。内部节点就是非叶子节点,内部节点不存储数据,只存储索引,数据都存储在叶子节点;②内部节点的key都按照从小到大的顺序排列,对于内部节点的一个key,左树中的所有key都小于它,右子树中的key都大于等于它,叶子节点中的记录也按照key的大小排列。③每个叶子节点都存有相邻叶子节点的指针,叶子节点本身依关键字的大小自小而大顺序链接。④父节点存有右孩子的第一个元素的索引。
    • B+树较B树的优势:①B+树的非叶子节点只是存储key,占用空间非常小,因此每一层的节点能索引到的数据范围更加的广。换句话说,每次IO操作可以搜索更多的数据。它更适合作为数据库MySQL的底层数据结构。②所有的查询都要查找到叶子节点,查询性能稳定,B树每个节点都可以查找到数据,所以不稳定。③所有的叶子节点形成了一个有序链表,更加便于查找。④叶子节点两两相连,符合磁盘的预读特性。比如叶子节点存储50和55,它有个指针指向了60和62这个叶子节点,那么当我们从磁盘读取50和55对应的数据的时候,由于磁盘的预读特性,会顺便把60和62对应的数据读取出来。这个时候属于顺序读取,而不是磁盘寻道了,加快了速度。⑤支持范围查询,而且部分范围查询非常高效,每个节点能索引的范围更大更精确,也意味着B+树单次磁盘IO的信息量大于B树,I/O效率更高。⑥数据都是存储在叶子节点这一层,并且有指针指向其他叶子节点,这样范围查询只需要遍历叶子节点这一层,无需整棵树遍历。⑦由于磁盘的存取速度与内存之间鸿沟,为了提高效率,要尽量减少磁盘I/O.磁盘往往不是严格按需读取,而是每次都会预读,磁盘读取完需要的数据,会顺序向后读一定长度的数据放入内存。而这样做的理论依据是计算机科学中著名的局部性原理:当一个数据被用到时,其附近的数据也通常会马上被使用,程序运行期间所需要的数据通常比较集中。

    24、B+树与哈希索引的区别

    • 哈希索引就是采用一定的哈希算法,把键值换算成新的哈希值,检索时不需要类似B+树那样从根节点到叶子节点逐级查找,只需一次哈希算法即可立刻定位到相应的位置,速度非常快。
    • 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据。
    • 如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索。
    • 哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询)
    • 哈希索引也不支持多列联合索引的最左匹配规则。
    • B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。

    25、MyISAM 和 InnoDB 的区别有哪些?

    • InnoDB支持事务,但但是MyISAM 不支持事务。这也是 MySQL 选择 InnoDB作为 默认存储引擎的原因之一。
    • InnoDB 支持外键,但是 MyISAM 不支持。如果一个表包含外键,并且存储引擎是InnoDB,把它转为 MyISAM就会失败。
    • InnoDB 使用的是聚集索引MyISAM使用非聚集索引。聚簇索引的文件存放在主键索引的叶子节点上,所以 InnoDB 必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。所以,主键不应该过大,因为主键太大,其他索引也都会很大。非聚集索引的话,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
    • InnoDB不保存表的具体行数,执行 select count(*) from table 时需要全表扫描。但是MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快。
    • InnoDB 最小的锁粒度是行级锁MyISAM 最小的锁粒度是表级锁。一个更新语句会锁住整张表,导致其他查询和更新都会被阻塞,所以并发访问受到很大的限制。

    26、如何选择存储引擎?

    • 是否支持事务。如果要请选择 InnoDB,如果不需要可以考虑 MyISAM。
    • 如果表中大多数都只是读查询,可以考虑MyISAM,如果既有读写还挺频繁,使用InnoDB
    • 系统崩溃后,MyISAM恢复起来更困难,能否接受,不能接受就选 InnoDB。、
    • MySQL5.5版本开始InnoDB已经成为MySQL的默认引擎。

    27、MySQL主从复制是怎么做的?

    • 主从复制主要涉及三个线程: binlog 线程、I/O 线程和 SQL 线程。这个过程是靠这三个过程的密切配合来进行的。
    • binlog线程:负责将主服务器上的数据更改写入二进制日志(Binary log)中。
    • I/O 线程 :负责从主服务器上读取二进制日志,并写入从服务器的中继日志(Relay log)。
    • SQL 线程 :负责读取中继日志,解析出主服务器已经执行的数据更改并在从服务器中重放(Replay)。
    • 主服务器-二进制日志(主服务器)-中继日志(从服务器)-从服务器(重放)

    28、大表如何优化?

    当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下:

    • 限定数据的范围:务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。
    • 读/写分离:经典的数据库拆分方案,主库负责写,从库负责读。
    • 垂直分区:根据数据库里面数据表的相关性进行拆分。 例如,用户表中既有用户的登录信息又有用户的基本信息,可以将用户表拆分成两个单独的表,甚至放到单独的库做分库。简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。垂直拆分的优点: 可以使得列数据变小,在查询时减少读取的Block数,减少I/O次数。此外,垂直分区可以简化表的结构,易于维护。垂直拆分的缺点: 主键会出现冗余,需要管理冗余列,并会引起Join操作,可以通过在应用层进行Join来解决。此外,垂直分区会让事务变得更加复杂。
    • 水平分区:保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。 水平拆分可以支撑非常大的数据量。水平拆分是指数据表行的拆分,表的行数超过200万行时,就会变慢,这时可以把一张的表的数据拆成多张表来存放。举个例子:我们可以将用户信息表拆分成多个用户信息表,这样就可以避免单一表数据量过大对性能造成影响。水平拆分可以支持非常大的数据量。需要注意的一点是:分表仅仅是解决了单一表数据过大的问题,但由于表的数据还是在同一台机器上,其实对于提升MySQL并发能力没有什么意义,所以 水平拆分最好分库 。水平拆分能够 支持非常大的数据量存储,应用端改造也少,但 分片事务难以解决 ,跨节点Join性能较差,逻辑复杂。

    29、平衡二叉搜索树和红黑树的区别?

    AVL和RBT都是二叉查找树的优化,其性能要远远好于二叉查找树。

    • 结构对比:AVL的结构高度平衡,RBT的结构基本平衡,平衡度AVL>RBT。
    • 查找对比:AVL查找时间复杂度最好,最坏情况是O(logN);RBT查找时间复杂度最好为O(logN)最坏比AVL略差。
    • 插入/删除对比:①AVL的插入和删除很容易造成树结构的不平衡,而RBT的平衡度要求较低。因此在大量数据插入的情况下,RBT需要通过旋转变色操作来重新达到平衡的频度要小于AVL。
    • 平衡处理:RBT比AVL多一种变色操作,而且变色的时间复杂度在O(logN)数量级上。但是由于操作简单,所以在实践中这种变色仍然是非常快速的。
    • 插入一个结点都引起了树的不平衡,AVL和RBT都最多需要2次旋转操作。但删除一个结点引起不平衡后,AVL最多需要logN 次旋转操作,而RBT最多只需要3次。因此两者插入一个结点的代价差不多,但删除一个结点的代价RBT要低一些。
    • AVL和RBT的插入删除代价主要是消耗在查找待操作的节点上,因此时间复杂度基本上都是于O(logN) 成正比的。
    • 大量数据实践证明,RBT的总体统计性能要好于平衡二叉树。

    30、Redis和Memcached的区别

    • 数据类型:Redis支持更丰富的数据类型(支持更复杂的场景):Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcached只支持简单的字符串类型。
    • 数据持久化:Redis支持数据持久化,可以将内存中的数据保持在磁盘中,重启的时候可以再次加载进行使用,而Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set,zset,hash等数据结构的存储。memcached只支持简单的字符串类型。
    • 集群模式:Redis 目前是原生支持 cluster 模式的。memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据。
    • 线程:Redis使用单线程的多路 I/O 复用模型。Memcached是多线程,非阻塞I/O复用的网络模型。

    31、Redis常见数据结构和使用场景分析

    • String:String数据结构是简单的Key-value类型,value其实不仅可以是String,也可以是数字。可以用作常规key-value缓存,也可以用来计数,比如记录微博数、粉丝数。
    • Hash:hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象,后续操作的时候,可以直接仅仅修改这个对象中的某个字段的值。 比如我们可以 hash 数据结构来存储用户信息,商品信息等等。
    • List:list 就是链表,list的应用场景非常多,也是Redis最重要的数据结构之一,比如微博的关注列表,粉丝列表,消息列表等功能都可以用Redis的 list 结构来实现。List底层是一个双向链表,即可以支持反向查找和白能力,更方便操作,但带来了额外的内存开销。
    • Set:set 对外提供的功能与list类似是一个列表的功能,特殊之处在于 set 是可以自动排重的。当你需要存储一个列表数据,又不希望出现重复数据时,set是一个很好的选择,并且set提供了判断某个成员是否在一个set集合内的重要接口,这个也是list所不能提供的。可以基于 set 轻易实现交集、并集、差集的操作。在微博应用中,可以将一个用户所有的关注人存在一个集合中,将其所有粉丝存在一个集合。Redis可以非常方便的实现如共同关注、共同粉丝、共同喜好等功能。这个过程也就是求交集的过程。
    • Sorted Set:和set相比,sorted set增加了一个权重参数score,使得集合中的元素能够按score进行有序排列。例如在直播系统中,实时排行信息包含直播间在线用户列表,各种礼物排行榜,弹幕消息(可以理解为按消息维度的消息排行榜)等信息,适合使用 Redis 中的 Sorted Set 结构进行存储。

    32、什么是AOF重写?

    AOF重写可以产生一个新的AOF文件,这个新的AOF文件和原有的AOF文件所保存的数据库状态一样,但体积更小。在执行 BGREWRITEAOF 命令时,Redis 服务器会维护一个 AOF 重写缓冲区,该缓冲区会在子进程创建新AOF文件期间,记录服务器执行的所有写命令。当子进程完成创建新AOF文件的工作之后,服务器会将重写缓冲区中的所有内容追加到新AOF文件的末尾,使得新旧两个AOF文件所保存的数据库状态一致。最后,服务器用新的AOF文件替换旧的AOF文件,以此来完成AOF文件重写操作。

    33、缓存雪崩和缓存穿透如何解决?

    • 缓存雪崩:是指缓存同一时间大面积失效,以致后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。
    • 解决方法:①事前:尽量保证整个Redis 集群的高可用性,发现机器宕机尽快补上。选择合适的内存淘汰策略。②事中:本地缓存+Hystrix限流和降级,避免MySQL崩掉。③利用Redis持久化机制将保存的数据尽快恢复缓存。
    • 缓存穿透:黑客故意去请求缓存中不存在数据,导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。
    • 解决方法:有很多种方法可以有效地解决缓存穿透问题,最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。另外一个更简单粗暴的方法,如果查询返回的数据为空(不管是数据不存在,还是系统故障)我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。

    34、数据库与数据仓库的区别

    • 数据仓库里是多个数据库以一种方式组织起来,数据仓库强调查询分析的速度,优化读取操作,主要目的是快速做大量数据的查询;数据仓库定期写入新数据,但不覆盖原有数据,而是给数据加上时间戳标签;数据仓库一般采用列存储。数据仓库的特征是面向主题、集成、相对稳定、反映历史变化、存储数历史数据。数据仓库的两个基本元素是维表和事实表。
    • 数据库强调范式,尽可能减少冗余,数据库采用行存储,数据库是面向事务的,存储在线交易数据。

    35、SQL的数据类型

    • 字符串:char、varchar、text
    • 二进制串:binary、varbinary
    • 布尔类型:boolean
    • 数值类型:integer、smallint、bigint、decimal、numeric、float、real、double
    • 时间类型:date、time、timestamp、interval

    36、left join,right join,inner join,full join之间的区别?

    • inner join(内连接),在两张表进行连接查询时,只保留两张表中完全匹配的结果集。
    • left join左连接,在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。
    • right join右连接,在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。
    • full join在两张表进行连接查询时,返回左表和右表中所有没有匹配的行。

    37、having和where的区别?

    • 本质区别时where筛选的时数据库表里面本来就有的字段,而having筛选的字段是从前筛选的字段筛选的。
    • where和having都可以使用的场景:
      1. select goods_price,goods_name from sw_goods where goods_price>100
      2. select goods_price,goods_name from sw_goods having goods_price>100

      原因是goods_price作为条件也出现在了查询的字段中。

    • 只可以使用where,不能使用having的场景:

      1. select goods_name,goods_number from sw_goods where goods_price>100
      2. select goods_name,goods_number from sw_goods having goods_price>100(X)

      原因是goods_price作为筛选条件没有出现在查询字段中,所以就会报错。having的原理是先select出来的进行筛选,而where是先筛选再select。

    • 只能使用having不能使用where的情况:

      1. select goods_category_id,avg(good_price) as ag from sw_goods group by goods_category having ag>1000
      2. select goods_category_id,avg(goods_price) as ag from sw_goods where ag>1000 group by goods_category(X)报错,这个表里没有这个ag这个字段。

      where子句中一般不使用聚合函数那种情况。

    38、not in 和not exists区别?

    • 如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引。
    • 而not exists的子查询依然能用到表上的索引。无论表多大,not exists都比not in大。

    39、mysql中设置row number?

    1. SET @row_number = 0;
    2. SELECT (@row_number:=@row_number + 1) AS num FROM table

    40、sql中null与''的区别?

    • null表示空,用is null表示
    • ''表示空字符串,用=‘’判断

    41、mysql中视图和表的区别?

    • 本质:表是内容,视图是窗口。视图是已经编译好的sql语句,是基于sql语句的结果集的可视化的表,而表不是。
    • 表是全局模式的实表,实表是局部模式的虚表。
    • 视图没有物理记录,而表有物理记录。
    • 表占用物理空间,而视图不占用。视图知识逻辑概念的存在,表可以及时对它进行修改,但视图只能用创建的语句来修改。
    • 视图的建立(create)和删除(drop)只影响视图本身,不影响对应的基本表。
    • 视图是查看数据表的一种方法,可以查询数据表中某些字段构成的数据,只是一些sql语句的集合。从安全的角度来说,视图可以防止用户接触数据表,因而用户不知道表结构。 

    42、视图与表的联系?

    视图是在基本表之上建立的表,它的结构(即所定义的列)和内容(即所有记录)都来自基本表,它依据基本表存在而存在。一个视图可以对应一个基本表,也可以对应多个基本表。视图是基本表的抽象和在逻辑意义上建立的新关系。

    43、如何写SQL求出中位数平均数和众数(除了用count之外的方法)?

    • 中位数:

      方案1(没考虑到偶数个数的情况):

      1. set @m = (select count(*)/2 from table)
      2. select column from table order by column limit @m, 1

    方案2(考虑偶数个数,中位数是中间两个数的平均):

    1. set @index = -1
    2. select avg(table.column)
    3. from(select @index:=@index+1 as index, column
    4. from table order by column) as t
    5. where t.index in (floor(@index/2),ceiling(@index/2))
    • 平均数:
    select avg(distinct column) from table
    • 众数
    select column, count(*) from table group by column order by column desc limit 1

    四、机器学习

    1、如何避免决策树过拟合?

    • 限制树深、剪枝、限制叶节点数量
    • 正则化、增加数据、数据增强(加入有噪音的数据)
    • bagging(subsample、subfeature、低维空间投影)、早停

    2、请说明随机森林较一般决策树稳定的几点原因?

    • bagging的方法,多个树投票提高泛化能力
    • bagging中引入随机(参数、样本、特征、空间映射),避免单棵树的过拟合,提高整体泛化能力。

    3、SVM的优缺点?

    • 优点:①能应用于非线性可分的情况②最后分类时由支持向量决定,复杂度取决于支持向量的数目而不是样本空间的维度,避免了维度灾难③具有鲁棒性,因为只使用少量支持向量,抓住关键样本,剔除冗余样本。④高维低样本下性能好,如文本分类。
    • 缺点:①模型训练复杂度高②难以适应多分类问题③核函数选择没有较好的方法论。

    4、SVM常见的核函数有哪些?

    • 线性核函数(Linear Kernel):线性核函数是SVM默认的核函数,它在线性可分的情况下使用较好。它的形式是K(x, y) = x * y,其中x和y是输入特征向量的内积。
    • 多项式核函数(Polynomial Kernel):多项式核函数可以处理一些非线性问题,它引入了多项式的概念。它的形式是K(x, y) = (ax * y + c)^d,其中a、c和d是用户定义的参数,d表示多项式的次数。
    • 径向基函数核函数(Radial Basis Function Kernel,RBF Kernel)or 高斯核函数:RBF核函数是SVM中最常用的非线性核函数之一,也叫高斯核函数。它的形式是K(x, y) = exp(-γ * ||x - y||^2),其中γ是用户定义的参数,||x - y||表示特征向量x和y之间的欧氏距离。
    • 布里曼核函数(Bhattacharyya Kernel):布里曼核函数通常用于处理概率分布的分类问题。它的形式是K(x, y) = exp(-D(x, y)),其中D(x, y)是x和y之间的布里曼距离。
    • sigmoid核函数(Sigmoid Kernel):Sigmoid核函数的形式是K(x, y) = tanh(ax * y + c),其中a和c是用户定义的参数,它可以用于一些非线性分类问题。
    • 自定义核函数(Custom Kernel):除了上述常见的核函数,SVM还支持使用自定义核函数,只要满足正定核函数的条件,就可以用于SVM。

    5、K-means的原理

    • 初始化k个点
    • 根据距离点归入k个类中
    • 更新k个类的类中心
    • 重复(2)(3),直到收敛或达到迭代次数

    6、K-Means算法原理及改进,遇到异常值怎么办?评估算法的指标有哪些?

    • Kmeans原理:在给定K值和K个初始类簇中心点的情况下,把每个点(亦即数据记录)分到离其最近的类簇中心点所代表的类簇中,所有点分配完毕之后,根据一个类簇内的所有点重新计算该类簇的中心点(取平均值),然后再迭代的进行分配点和更新类簇中心点的步骤,直至类簇中心点的变化很小,或者达到指定的迭代次数。
    • 改进:

      a. kmeans++:初始随机点选择尽可能远,避免陷入局部解。方法是n+1个中心点选择时,对于离前n个点选择到的概率更大。

      b. mini batch kmeans:每次只用一个子集做重入类并找到类心(提高训练速度)。

      c. ISODATA:对于难以确定k的时候,使用该方法。思路是当类下的样本小时,剔除;类下样本数量多时,拆分。

      d. kernel kmeans:kmeans用欧氏距离计算相似度,也可以使用kernel映射到高维空间再聚类。

    • 遇到异常值:

      有条件的话使用密度聚类或者一些软聚类的方式先聚类,剔除异常值。不过本来用kmeans就是为了快,这么做有些南辕北辙了。

      b. 局部异常因子LOF:如果点p的密度明显小于其邻域点的密度,那么点p可能是异常值
      (参考:https://blog.csdn.net/wangyibo0201/article/details/51705966)

      c. 多元高斯分布异常点检测

      d. 使用PCA或自动编码机进行异常点检测:使用降维后的维度作为新的特征空间,其降维结果可以认为剔除了异常值的影响(因为过程是保留使投影后方差最大的投影方向)

      e. isolation forest:基本思路是建立树模型,一个节点所在的树深度越低,说明将其从样本空间划分出去越容易,因此越可能是异常值。是一种无监督的方法,随机选择n个sumsampe,随机选择一个特征一个值。
      (参考:https://blog.csdn.net/u013709270/article/details/73436588)

      f. winsorize:对于简单的,可以对单一维度做上下截取

    • 评估聚类算法的指标:

      a. 外部法(基于有标注):Jaccard系数、纯度

      b. 内部法(无标注):内平方和WSS和外平方和BSS

      c. 此外还要考虑到算法的时间空间复杂度、聚类稳定性等。

    7、主成分分析PCA方法

    主成分分析法时一种降维的方法。思想是将样本从原来的特征空间转化到新的特征空间,并且样本在新特征空间坐标轴上的投影方差尽可能大,这样就能涵盖样本最主要的信息。

    • 特征归一化
    • 求样本特征的协方差矩阵A
    • 求A的特征值和特征向量,即AX=λX
    • 将特征值从小到大排列,选择topK。对应得特征向量就是新的坐标轴。

    8、数据预处理过程有哪些?

    • 缺失值处理:删、插
    • 异常值处理
    • 特征转换:时间特征sin化表示
    • 标准化:最大最小标准化、z标准化等
    • 归一化:对于文本或评分特征,不同样本之间可能有整体上的差异,如a文本共20个词,b文本30000个词,b文本中各个维度上的频次都很可能远远高于a文本
    • 离散化:one-hot,分箱等。

    9、数据清理中,处理缺失值的方法是?

    由于调查、编码和录入误差,数据中可能存在一些无效值和缺失值,需要给予适当的处理。常用的处理方法有:估算,整例删除,变量删除和成对删除。

    (1)估算(estimation)。最简单的办法就是用某个变量的样本均值、中位数或众数代替无效值和缺失值。这种办法简单,但没有充分考虑数据中已有的信息,误差可能较大。另一种办法就是根据调查对象对其他问题的答案,通过变量之间的相关分析或逻辑推论进行估计。例如,某一产品的拥有情况可能与家庭收入有关,可以根据调查对象的家庭收入推算拥有这一产品的可能性。

    (2)整例删除(casewise deletion)是剔除含有缺失值的样本。由于很多问卷都可能存在缺失值,这种做法的结果可能导致有效样本量大大减少,无法充分利用已经收集到的数据。因此,只适合关键变量缺失,或者含有无效值或缺失值的样本比重很小的情况。

    (3)变量删除(variable deletion)。如果某一变量的无效值和缺失值很多,而且该变量对于所研究的问题不是特别重要,则可以考虑将该变量删除。这种做法减少了供分析用的变量数目,但没有改变样本量。

    (4)成对删除(pairwise deletion)是用一个特殊码(通常是9、99、999等)代表无效值和缺失值,同时保留数据集中的全部变量和样本。但是,在具体计算时只采用有完整答案的样本,因而不同的分析因涉及的变量不同,其有效样本量也会有所不同。这是一种保守的处理方法,最大限度地保留了数据集中的可用信息。

    10、余弦距离与欧式距离求相似度的差别?

    • 欧氏距离能够体现个体数值特征的绝对差异,所以更多的用于需要从维度的数值大小中体现差异的分析,如使用用户行为指标分析用户价值的相似度或差异。
    • 余弦距离更多的是从方向上区分差异,而对绝对的数值不敏感,更多的用于使用用户对内容评分来区分兴趣的相似度和差异,同时修正了用户间可能存在的度量标准不统一的问题(因为余弦距离对绝对数值不敏感)。
    • 总体来说,欧氏距离体现数值上的绝对差异,而余弦距离体现方向上的相对差异

      (1)例如,统计两部剧的用户观看行为,用户A的观看向量为(0,1),用户B为(1,0);此时二者的余弦距很大,而欧氏距离很小;我们分析两个用户对于不同视频的偏好,更关注相对差异,显然应当使用余弦距离。
      (2)而当我们分析用户活跃度,以登陆次数(单位:次)和平均观看时长(单:分钟)作为特征时,余弦距离会认为(1,10)、(10,100)两个用户距离很近;但显然这两个用户活跃度是有着极大差异的,此时我们更关注数值绝对差异,应当使用欧氏距离。

    11、GBDT(梯度提升树)?

    • 首先介绍Adaboost Tree,是一种boosting的树集成方法。基本思路是依次训练多棵树,每棵树训练时对分错的样本进行加权。树模型中对样本的加权实际是对样本采样几率的加权,在进行有放回抽样时,分错的样本更有可能被抽到
    • GBDT是Adaboost Tree的改进,每棵树都是CART(分类回归树),树在叶节点输出的是一个数值,分类误差就是真实值减去叶节点的输出值,得到残差。GBDT要做的就是使用梯度下降的方法减少分类误差值。
    • 在GBDT的迭代中,假设我们前一轮迭代得到的强学习器是ft−1(x), 损失函数是L(y,ft−1(x)), 我们本轮迭代的目标是找到一个CART回归树模型的弱学习器ht(x),让本轮的损失损失L(y,ft(x)=L(y,ft−1(x)+ht(x))最小。也就是说,本轮迭代找到决策树,要让样本的损失尽量变得更小。
    • GBDT的思想可以用一个通俗的例子解释,假如有个人30岁,我们首先用20岁去拟合,发现损失有10岁,这时我们用6岁去拟合剩下的损失,发现差距还有4岁,第三轮我们用3岁拟合剩下的差距,差距就只有一岁了。如果我们的迭代轮数还没有完,可以继续迭代下面,每一轮迭代,拟合的岁数误差都会减小。得到多棵树后,根据每颗树的分类误差进行加权投票。

    五、业务场景问题

    1、处理需求时的一般思路是什么?

    • 明确需求,需求方的目的是什么
    • 拆解任务
    • 制定可执行方案
    • 推进
    • 验收

    2、如何分析次日留存率下降的问题?

    次日留存率是用于衡量用户在首次使用后是否继续使用产品或服务的情况,用于评估用户的忠诚度和产品吸引力。次日留存率 = (第二天继续使用的用户数 / 首次使用的用户数) × 100%

    • 两层模型:从用户画像、渠道、产品、行为环节等角度细分,明确到底是哪里的次日留存率下降了。
    • 指标拆解:次日留存率 = Σ 次日留存数 / 今日获客人数
    • 原因分析

       (1)内部:

           a. 运营活动

           b. 产品变动

           c. 技术故障

           d. 设计漏洞(如产生可以撸羊毛的设计)

      (2)外部:

            a. 竞品

           b. 用户偏好

           c. 节假日

           d. 社会事件(如产生舆论)
       

    3、给你一个无序数组,怎么才能合理采样?

    • 无序数组是相对有序数组而言的,无序数组并不等于随机,我们要做的是将无序数组洗牌,得到随机排列。
    • 对于无序数组,n个元素能产生n!种排序。如果洗牌算法能产生n!种不同的结果,并且这些结果产生的概率相等,那么这个洗牌算法是正确的。方法:for i in range(len(n)): swap(arr[i], arr[random(i,n)]),这段代码是对随机确定数组第一位的值,然后递归对剩余的数组进行相同的过程,可以产生n!中等可能的排序情况。

    4、如果次日用户留存率下降了5%该怎么分析?

    • 首先采用“两层模型”分析:对用户进行细分,包括新老、渠道、活动、画像等多个维度,然后分别计算每个维度下不同用户的次日留存率。通过这种方法定位到导致留存率下降的用户群体是谁。
    • 对于目标群体次日留存下降问题,具体情况具体分析。具体分析可以采用“内部-外部”因素考虑内部因素分为获客(渠道质量低、活动获取非目标用户)、满足需求(新功能改动引发某类用户不满)、提活手段(签到等提活手段没达成目标、产品自然使用周期低导致上次获得的大量用户短期内不需要再使用等);外部因素采用PEST分析,政治(政策影响)、经济(短期内主要是竞争环境,如对竞争对手的活动)、社会(舆论压力、用户生活方式变化、消费心理变化、价值观变化等偏好变化)、技术(创新解决方案的出现、分销渠道变化等)

    5、卖玉米如何提高收益?价格提高多少才能获取最大收益?

    收益=单价*销售量,那么我们的策略是提高单位溢价或者提高销售规模。

    • 提高单位溢价:

    ​​​​​​​(1)品牌打造获得长期溢价,但缺陷是需要大量前期营销投入;
    (2)加工商品占据价值链更多环节,如熟玉米、玉米汁、玉米蛋白粉;重定位商品,如礼品化等;
    (3)价格歧视,根据价格敏感度对不同用户采用不同定价。

    • 销售量=流量 x 转化率,上述提高单位溢价的方法可能对流量产生影响,也可能对转化率产生影响。
    • 收益 = 单价 x 流量 x 转化率,短期内能规模化采用的应该是进行价格歧视,如不同时间、不同商圈的玉米价格不同,采取高定价,然后对价格敏感的用户提供优惠券等。

    6、怎么做恶意刷单检测?

    分类问题用机器学习方法建模解决,我想到的特征有:

    • 商家特征:商家历史销量、信用、产品类别、发货快递公司等
    • 用户行为特征:用户信用、下单量、转化率、下单路径、浏览店铺行为、支付账号
    • 环境特征(主要是避免机器刷单):地区、ip、手机型号等
    • 异常检测:ip地址经常变动、经常清空cookie信息、账号近期交易成功率上升等
    • 评论文本检测:刷单的评论文本可能套路较为一致,计算与已标注评论文本的相似度作为特征
    • 图片相似度检测:同理,刷单可能重复利用图片进行评论

    7、类比到头条的收益,头条放多少广告可以获得最大收益,不需要真的计算,只需要有个思路。

    收益 = 出价x流量x点击率x有效转化率,放广告的数量会提高流量,但会降低匹配程度,因此降低点击率。最大收益是找到这个乘积的最大值,是一个有约束条件的最优化问题。同时参考价格歧视方案,可以对不同的用户投放不同数量的广告。

    8、费米估计:不用任何公开参考资料,估算今年新生儿出生数量

    • 采用两层模型(人群画像 人群转化):新生儿出生数=Σ各年龄层育龄女性数量各年龄层生育比率。
    • 从数字到数字,如果有前几年新生儿出生数量数据,建立时间序列模型(需要考虑二胎放开的突变事件)进行预测。
    • 找先兆指标,如婴儿类用品的新增活跃用户数量X表示新生儿家庭用户。Xn/新生儿n为该年新生儿家庭用户的转化率,如X2007/新生儿2007位为2007年新生儿家庭用户的转化率。该转化率会随平台发展而发展,可以根据往年数量推出今年的大致转化率,并根据今年新增新生儿家庭用户数量推出今年估计的新生儿数量。
       

    六、AB测试问题 

    1、A/B test是什么?

    A/B测试(也称为分割测试或桶测试)是一种将网页或应用程序的两个版本相互比较以确定哪个版本的性能更好的方法。AB测试本质上是一个实验,其中页面的两个或多个变体随机显示给用户,统计分析确定哪个变体对于给定的转换目标(指标如CTR)效果更好。

    2、AB测试工作原理。

    在AB测试中你可以设置访问网页或应用并对其进行修改以创建同一页面的第二个版本。这个更改可以像单个标题或按钮一样简单,也可以是完整的页面重新设计。然后一半的流量显示页面的原始版本(称为控件),另一半显示页面的修改版本(称为变体)。

    当用户访问页面时,如上如灰色按钮(控件)和箭头所指红色按钮(变体),利用埋点可以对用户点击行为数据采集,并通过统计引擎进行分析(进行A/B test)。然后,就可以确定这种更改(变体)对于给定的指标(这里是用户点击率CTR)产生正向影响、负向影响或无影响。实验数据结果可能如下:

    3、进行A/B测试的目的是什么?

    A/B测试可以让个人、团队和公司通过用户行为结果数据不断对其用户体验进行仔细更改。这允许他们构建假设,并更好地了解为什么修改的某些元素会影响用户行为。这些假设可能被证明是错误的,也就是说他们对特定目标的最佳体验的个人或团队想法利用A / B test证明对用户来说是行不通的,当然也可能证明是正确的。所以说 A/B test不仅仅是解决一次分歧的对比,A/B test可以持续使用,以不断改善用户的体验,改善某一目标,如随着时间推移的转换率。

    4、AB测试的流程

    • 确定目标:目标是用于确定变体是否比原始版本更成功的指标。可以是点击按钮的点击率、链接到产品的打开率,电子邮件注册的注册率等等。
    • 创建变体:对网站原有版本的元素进行所需的更改,可能是更改按钮是颜色,交换页面上元素的顺序,隐藏导航元素或完全自定义内容
    • 生成假设:一旦确定了目标,就可以开始生成AB测试想法和假设,以便统计分析它们是否会优于当前版本。
    • 收集数据:针对指定区域的假设收集相对应的数据用于A/B test分析。
    • 运行试验:此时,网站或应用的访问者将被随机分配控件或变体。测量,计算和比较他们与每种体验的相互作用,以确定每个用户体验的表现。
    • 分析结果:实验完成后,就可以分析结果了。A / B test分析将显示两个版本之间是否存在统计性显著差异。

    5、AB测试需要注意的点

    • 先验性:通过低代价,小流量的实验,再推广到全流量的用户。
    • 并行性:不同版本、不同方案在验证时,要保证其他条件都一样。
    • 分流科学性和数据科学性:分流科学是指对AB两组分配的数据要一致,数据科学性是指不能直接用均值转化率、均值点击率来进行AB测试决策,而是要通过置信区间、假设检验、收敛程度来得出结论。

    6、A/B test中要知道的统计学知识?

    • 点估计
    • 区间估计
    • 中心极限定理(样本估计总体的核心,可以对比看一下大数定理)
    • 假设检验(其中假设检验部分为核心,其他辅助更好的理解该部分内容,比如区间估计可以理解为正向的推断统计,假设检验可以理解为反证的推断统计,关于假设检验本身,你可能还需要知道小概率事件、t分布、z分布、卡方分布、p值、alpha错误、belta错误等内容。)

    7、AB测试简例(结合python实现)

    实例背景简述:

    某司「猜你想看」业务接入了的新推荐算法,新推荐策略算法开发完成后,在全流量上线之前要评估新推荐策略的优劣,所用的评估方法是A/B test,具体做法是在全量中抽样出两份小流量,分别走新推荐策略分支和旧推荐策略分支,通过对比这两份流量下的指标(这里按用户点击衡量)的差异,可以评估出新策略的优劣,进而决定新策略是否全适合全流量。

    • 指标CTR

      CTR用于测量某个广告、链接或元素在用户看到它后被点击的概率。它通常以百分比形式表示,计算公式如下:

      \text{CTR} = \left( \frac{\text{点击次数}}{\text{广告或链接展示次数}} \right) \times 100\%CTR=(广告或链接展示次数点击次数​)×100%

    • 变体:新的推荐策略

    • 假设:新的推荐策略可以带来更多的用户点击

    • 收集数据:以下B组数据为我们想验证的新的策略结果数据,A组数据为旧的策略结构数据。均为伪造数据。

    • 分析结果:利用python中的scipy.stats.ttest_ind做关于两组数据的双边t检验(均值比较),结果比较简单。但是做大于或者小于的单边检测的时候需要做一些处理,才能得到正确的结果。

      1. from scipy import stats
      2. import numpy as np
      3. import numpy as np
      4. import seaborn as sns
      5. A = np.array([ 1, 4, 2, 3, 5, 5, 5, 7, 8, 9,10,18])
      6. B = np.array([ 1, 2, 5, 6, 8, 10, 13, 14, 17, 20,13,8])
      7. print('策略A的均值是:',np.mean(A))
      8. print('策略B的均值是:',np.mean(B))
      1. Output:
      2. 策略A的均值是:6.416666666666667
      3. 策略B的均值是:9.75

      很明显,策略B的均值大于策略A的均值,但这就能说明策略B可以带来更多的业务转化吗?还是说仅仅是由于一些随机的因素造成的。

    • 我们是想证明新开发的策略B效果更好,所以可以设置原假设和备择假设分别是:H0:A>=B;H1:A < B

    scipy.stats.ttest_ind(x,y)默认验证的是x.mean()-y.mean()这个假设。为了在结果中得到正数,计算如下:

    stats.ttest_ind(B,A,equal_var= False)
    
    1. output:
    2. Ttest_indResult(statistic=1.556783470104261, pvalue=0.13462981561745652)

    根据 scipy.stats.ttest_ind(x, y) 文档的解释,这是双边检验的结果。为了得到单边检验的结果,需要将计算出来的 pvalue 除于2 取单边的结果(这里取阈值为0.05)。求得pvalue=0.13462981561745652,p/2 > alpha(0.05),所以不能够拒绝假设,暂时不能够认为策略B能带来多的用户点击。

    8、什么是数据埋点?

    数据埋点是一种移动端APP常规的数据采集方法。埋点是数据采集的一种方法,将移动APP每个功能需要统计的点击行为页面上的功能使用情况采集相应的信息和行为。无论是产品的迭代还是运营的策略,都是需要有详细的数据支撑来针对性的做下一步迭代和运营决策。

    9、埋点方式有哪些?

    埋点方式从数据来源分为客户端埋点服务端埋点

    • 客户端埋点:理解为用户行为操作的数据采集,服务端是用户通过客户端发生请求获取反馈的数据采集,选择不同方式的场景主要涉及哪些呢,譬如我们在收集APP端频繁的操作刷新、点返回,这些操作行为的数据大多数采用客户端埋点方式,适用于大量频繁的操作并不需要实时反馈信息的场景,同时客户端具有缓存的功能,这样的埋点方式不仅对客户的产品体验好,可以减轻服务器端的信息交互压力。
    • 服务端埋点:更使用于交互少,数据反馈要求实时性高,比如新闻信息的变化,比如答题的答案选项、对错情况。

    10、客户端和服务端的埋点方式的优缺点有哪些?

    • 客户端埋点优点:采集的APP端页面展示、点击行为、不需要请求服务器的数据
    • 客户端埋点缺点:无网络时数据不完整、实时性有延迟;当需要改变埋点时,必须更新版本。
    • 服务端埋点优点:实时性好,数据准确。变更成本低,能够收集不在APP内发生的行为,只要请求服务器就行,如统计从其他APP引流的安装量。
    • 服务端埋点缺点:不能收集不需要请求服务器的数据,用户不联网不能采集数据。

    七、Python问题

    1、常用的Python库有哪些?

    numpy 矩阵运算;sklearn 常用机器学习和数据挖掘工具库;scipy 基于numpy做高效的数学计算,如积分、线性代数、稀疏矩阵等; pandas: 将数据用表的形式进行操作;matplotlib: 数据可视化工具;seaborn:数据可视化工具;keras/tensorflow/theano:深度学习工具包;NLTK:自然语言处理工具包; beautifulsoap:网页文档解析工具。

    八、大数据问题

    1、hadoop原理和mapreduce原理

    • hadoop原理:采用HDFS分布式存储文件,MapReduce分解计算。
    • MapReduce原理:①map阶段:读取HDFS中的文件,解析成的形式,并对进行分区(默认一个区),将相同k的value放在一个集合中。②reduce阶段:将map的输出copy到不同的reduce节点上,节点对Map的输出进行合并,排序。
  • 相关阅读:
    Prometheus Operator与kube-prometheus之二-如何监控1.23+ kubeadm集群
    如何学习BCGControlBar?
    今天的码农女孩总结了jQuery处理缓存的方法和事件委托方法的区别的笔记
    ModStartCMS v7.6.0 CMS备份恢复优化,主题开发文档更新
    MindSpore自定义算子中的张量维度问题
    SpringBoot技术在商场应急管理中的创新应用
    注册会计师怎么注册非执业?注会执业与非执业有何区别
    携手华为,微想科技正式启动“720云”鸿蒙原生应用开发
    推荐几款好用的MySQL开源客户端,建议收藏
    Tensorflow安装GPU版本的一些问题处理
  • 原文地址:https://blog.csdn.net/qq_43687860/article/details/132756431