[关闭]
@lifei6671 2019-11-27T04:23:45.000000Z 字数 15839 阅读 321

PHP 基础

1. PHP里的超全局变量

  1. $GLOBALS
  2. $_SERVER
  3. $_GET
  4. $_POST
  5. $_FILES
  6. $_COOKIE
  7. $_SESSION
  8. $_REQUEST
  9. $_ENV

2. php7新特性

3. php7卓越性能背后的优化

4. include、require、include_once、require_once 的区别

require 和 include 几乎完全一样,除了处理失败的方式不同之外。require 在出错时产生 E_COMPILE_ERROR 级别的错误。换句话说将导致脚本中止而 include 只产生警告(E_WARNING),脚本会继续运行

include_once 语句在脚本执行期间包含并运行指定文件。此行为和 include 语句类似,唯一区别是如果该文件中已经被包含过,则不会再次包含。如同此语句名字暗示的那样,只会包含一次

5. 浮点型储存原理

  1. <?php
  2. $f = 0.58;
  3. var_dump(intval($f * 100)); //为啥输出57
  4. ?>

这里的关键点就在于, 小数在二进制的表示, 关于小数如何用二进制表示,:

将该数字乘以2,取出整数部分作为二进制表示的第1位;然后再将小数部分乘以2,将得到的整数部分作为二进制表示的第2位;以此类推,知道小数部分为0。
特殊情况: 小数部分出现循环,无法停止,则用有限的二进制位无法准确表示一个小数,这也是在编程语言中表示小数会出现误差的原因

下面我们具体计算一下0.6的小数表示过程

  1. 0.6 * 2 = 1.2 ——————- 1
  2. 0.2 * 2 = 0.4 ——————- 0
  3. 0.4 * 2 = 0.8 ——————- 0
  4. 0.8 * 2 = 1.6 ——————- 1
  5. 0.6 * 2 = 1.2 ——————- 1
  6. …………

6. PHP单例实现

  1. class Config {
  2. private static $instance = null;
  3. private function __construct(){}
  4. private function __clone(){}
  5. public static function getInstance() {
  6. if self::$instance == null {
  7. self::$instance = new self();
  8. }
  9. return self::$instance;
  10. }
  11. }

7. PHP7垃圾回收原理

PHP7垃圾回收原理

PHP变量的内存管理通过引用计数机制实现,当变量赋值、传递时并不会直接硬拷贝,而是增加value的引用数,unset、return等释放变量时再减掉引用数,减掉后如果发现refcount变为0则直接释放value,这是变量的基本gc过程,PHP正是通过这个机制实现的自动垃圾回收,但是有一种情况是这个机制无法解决的,从而因变量无法回收导致内存始终得不到释放,这种情况就是循环引用,简单的描述就是变量的内部成员引用了变量自身,比如数组中的某个元素指向了数组,这样数组的引用计数中就有一个来自自身成员,试图释放数组时因为其refcount仍然大于0而得不到释放,而实际上已经没有任何外部引用了,这种变量不可能再被使用,所以PHP引入了另外一个机制用来处理变量循环引用的问题。

一个变量只能加入一次buffer,为了防止重复加入,变量加入后会把zend_refcounted_h.gc_info置为GC_PURPLE,即标为紫色,下次refcount减少时如果发现已经加入过了则不再重复插入。垃圾缓存区是一个双向链表,等到缓存区满了以后则启动垃圾检查过程:遍历缓存区,再对当前变量的所有成员进行遍历,然后把成员的refcount减1(如果成员还包含子成员则也进行递归遍历,其实就是深度优先的遍历),最后再检查当前变量的引用,如果减为了0则为垃圾。这个算法的原理很简单,垃圾是由于成员引用自身导致的,那么就对所有的成员减一遍引用,结果如果发现变量本身refcount变为了0则就表明其引用全部来自自身成员。具体的过程如下:

8. php二进制安全的含义

在PHP文档里,有时会看到“二进制安全的”这样的描述,基本就是这么一个意思:类似的功能,在C语言里的函数会对有些字符进行特别处理,而PHP这个函数对于所有字符一视同仁,不用担心会有特殊字符影响处理,特别不用担心编码0字符。

PHP里,有string的概念。string里,每个字符的类型为byte(与PHP相比,Java的每个字符为Character,是UTF8字符,C语言的每个字符可以在编译时选择)。

byte里,有ASCII代码的字符,例如ABC,123,abc,也有一些特殊字符,例如回车,退格之类的。

特殊字符很多是不能显示的。或者说,他们的显示方式没有标准,例如编码65到哪儿都是字母A,编码97到哪儿都是字符a。而退格键却在有的地方显示成一个符号,在有的地方就会真的把前一个字符退掉。
PHP以C为基础,所以很多描述都是以C为对比。C的字符串里,一种经典的定义就是,以编码0作为字符串的结尾。那么,假设这样一个string,里面3个字符的编码分别是97,0,97。那么,C里面如果有str_replace等效的函数, 利用它把97换成98,那么这个函数读取到0的时候,就认为已经结束了,就会得到98,0,97,这就是“二进制不安全”。跟它对应的,PHP里的str_replace是二进制安全的,那么这个0不会被视为特殊的结束符号,于是结果就是98,0,98,这是我们期望的结果。

9. PHP 所有魔术变量

  1. __DIR__ //当前脚本目录
  2. __LINE__ //当前行数
  3. __METHOD__ //当前执行的方法
  4. __FUNCTION__ //当前执行的函数名
  5. __CLASS__ //当前执行的类
  6. __FILE__ //当前执行的脚本名称
  7. __NAMESPACE__ //当前的命名空间
  8. __TRAIT__ //当前的代码片段

PHP 常见算法题目

1. 反转函数的实现

  1. /**
  2. * 反转数组
  3. * @param array $arr
  4. * @return array
  5. */
  6. function reverse($arr)
  7. {
  8. $n = count($arr);
  9. $left = 0;
  10. $right = $n - 1;
  11. while ($left < $right) {
  12. $temp = $arr[$left];
  13. $arr[$left++] = $arr[$right];
  14. $arr[$right--] = $temp;
  15. }
  16. return $arr;
  17. }

2.两个有序int集合是否有相同元素的最优算法

  1. /**
  2. * 寻找两个有序数组里相同的元素
  3. * @param array $arr1
  4. * @param array $arr2
  5. * @return array
  6. */
  7. function find_common($arr1, $arr2)
  8. {
  9. $common = array();
  10. $i = $j = 0;
  11. $count1 = count($arr1);
  12. $count2 = count($arr2);
  13. while ($i < $count1 && $j < $count2) {
  14. if ($arr1[$i] < $arr2[$j]) {
  15. $i++;
  16. } elseif ($arr1[$i] > $arr2[$j]) {
  17. $j++;
  18. } else {
  19. $common[] = $arr[$i];
  20. $i++;
  21. $j++;
  22. }
  23. }
  24. return array_unique($common);
  25. }

3.将一个数组中的元素随机(打乱)

  1. /**
  2. * 打乱数组
  3. * @param array $arr
  4. * @return array
  5. */
  6. function custom_shuffle($arr)
  7. {
  8. $n = count($arr);
  9. for ($i = 0; $i < $n; $i++) {
  10. $rand_pos = mt_rand(0, $n - 1);
  11. if ($rand_pos != $i) {
  12. $temp = $arr[$i];
  13. $arr[$i] = $arr[$rand_pos];
  14. $arr[$rand_pos] = $temp;
  15. }
  16. }
  17. return $arr;
  18. }
  19. 4.给一个有数字和字母的字符串,让连着的数字和字母对应#
  20. function number_alphabet($str)
  21. {
  22. $number = preg_split('/[a-z]+/', $str, -1, PREG_SPLIT_NO_EMPTY);
  23. $alphabet = preg_split('/\d+/', $str, -1, PREG_SPLIT_NO_EMPTY);
  24. $n = count($number);
  25. for ($i = 0; $i < $count; $i++) {
  26. echo $number[$i] . ':' . $alphabet[$i] . '</br>';
  27. }
  28. }
  29. $str = '1a3bb44a2ac';
  30. number_alphabet($str);//1:a 3:bb 44:a 2:ac

5.求n以内的质数(质数的定义:在大于1的自然数中,除了1和它本身意外,无法被其他自然数整除的数)

思路:

  1. (质数筛选定理)n不能够被不大于根号n的任何质数整除,则n是一个质数
  2. 除了2的偶数都不是质数

代码如下:

  1. /**
  2. * 求n内的质数
  3. * @param int $n
  4. * @return array
  5. */
  6. function get_prime($n)
  7. {
  8. $prime = array(2);//2为质数
  9. for ($i = 3; $i <= $n; $i += 2) {//偶数不是质数,步长可以加大
  10. $sqrt = intval(sqrt($i));//求根号n
  11. for ($j = 3; $j <= $sqrt; $j += 2) {//i是奇数,当然不能被偶数整除,步长也可以加大。
  12. if ($i % $j == 0) {
  13. break;
  14. }
  15. }
  16. if ($j > $sqrt) {
  17. array_push($prime, $i);
  18. }
  19. }
  20. return $prime;
  21. }
  22. print_r(getPrime(1000));

6.约瑟夫环问题

相关题目:一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数, 再数到第m只,在把它踢出去…,如此不停的进行下去, 直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n, 输出最后那个大王的编号。

  1. /**
  2. * 获取大王
  3. * @param int $n
  4. * @param int $m
  5. * @return int
  6. */
  7. function get_king_mokey(int $n,int $m)
  8. {
  9. $arr = range(1, $n);//创建N个元素的数组
  10. $i = 0;
  11. while (count($arr) > 1) { //不断的循环
  12. $i++;
  13. $survice = array_shift($arr); //队首的出队
  14. if ($i % $m != 0) { //如果不符合第m个则再入队
  15. array_push($arr, $survice);
  16. }
  17. }
  18. return $arr[0];
  19. }

7.如何快速寻找一个数组里最小的1000个数

思路:假设最前面的1000个数为最小的,算出这1000个数中最大的数,然后和第1001个数比较,如果这最大的数比这第1001个数小的话跳过,如果要比这第1001个数大则将两个数交换位置,并算出新的1000个数里面的最大数,再和下一个数比较,以此类推。
代码如下:

  1. //寻找最小的k个数
  2. //题目描述
  3. //输入n个整数,输出其中最小的k个。
  4. /**
  5. * 获取最小的k个数
  6. * @param array $arr
  7. * @param int $k [description]
  8. * @return array
  9. */
  10. function get_min_array($arr, $k)
  11. {
  12. $n = count($arr);
  13. $min_array = array();
  14. for ($i = 0; $i < $n; $i++) {
  15. if ($i < $k) {
  16. $min_array[$i] = $arr[$i];
  17. } else {
  18. if ($i == $k) {
  19. $max_pos = get_max_pos($min_array);
  20. $max = $min_array[$max_pos];
  21. }
  22. if ($arr[$i] < $max) {
  23. $min_array[$max_pos] = $arr[$i];
  24. $max_pos = get_max_pos($min_array);
  25. $max = $min_array[$max_pos];
  26. }
  27. }
  28. }
  29. return $min_array;
  30. }
  31. /**
  32. * 获取最大的位置
  33. * @param array $arr
  34. * @return array
  35. */
  36. function get_max_pos($arr)
  37. {
  38. $pos = 0;
  39. for ($i = 1; $i < count($arr); $i++) {
  40. if ($arr[$i] > $arr[$pos]) {
  41. $pos = $i;
  42. }
  43. }
  44. return $pos;
  45. }
  46. $array = [1, 100, 20, 22, 33, 44, 55, 66, 23, 79, 18, 20, 11, 9, 129, 399, 145, 2469, 58];
  47. $min_array = get_min_array($array, 10);
  48. print_r($min_array);

8.如何在有序的数组中找到一个数的位置(二分查找)

代码如下:

  1. /**
  2. * 二分查找
  3. * @param array $array 数组
  4. * @param int $n 数组数量
  5. * @param int $value 要寻找的值
  6. * @return int
  7. */
  8. function binary_search($array, $n, $value)
  9. {
  10. $left = 0;
  11. $right = $n - 1;
  12. while ($left <= $right) { //只要没有重合就一直循环
  13. $mid = intval(($left + $right) / 2); //需要知道两个区间的中间值
  14. if ($value > $array[$mid]) { //跟中间值比较大小
  15. $right = $mid + 1; //如果比中间值大,说明在左侧,这个跟数组的排序有关
  16. } elseif ($value < $array[$mid]) {
  17. $left = $mid - 1;
  18. } else {
  19. return $mid;
  20. }
  21. }
  22. return -1;
  23. }

9.给定一个有序整数序列,找出绝对值最小的元素

思路:二分查找

  1. /**
  2. * 获取绝对值最小的元素
  3. * @param array $arr
  4. * @return int
  5. */
  6. function get_min_abs_value($arr)
  7. {
  8. $n = count($arr);
  9. //如果符号相同,直接返回
  10. if (is_same_sign($arr[0], $arr[$n - 1])) {
  11. return $arr[0] >= 0 ? $arr[0] : $arr[$n - 1];
  12. }
  13. //二分查找
  14. $left = 0;
  15. $right = $n - 1;
  16. while ($left <= $right) {
  17. if ($left + 1 === $right) {
  18. return abs($arr[$left]) < abs($arr[$right]) ? $arr[$left] : $arr[$right];
  19. }
  20. $mid = intval(($left + $right) / 2);
  21. if ($arr[$mid] < 0) {
  22. $left = $mid + 1;
  23. } else {
  24. $right = $mid - 1;
  25. }
  26. }
  27. }
  28. /**
  29. * 判断符号是否相同
  30. * @param int $a
  31. * @param int $b
  32. * @return boolean
  33. */
  34. function is_same_sign($a, $b)
  35. {
  36. if ($a * $b > 0) {
  37. return true;
  38. } else {
  39. return false;
  40. }
  41. }

10.找出有序数组中随机3个数和为0的所有情况

思路:动态规划

  1. function three_sum($arr)
  2. {
  3. $n = count($arr);
  4. $return = array();
  5. for ($i=0; $i < $n; $i++) {
  6. $left = $i + 1;
  7. $right = $n - 1;
  8. while ($left <= $right) {
  9. $sum = $arr[$i] + $arr[$left] + $arr[$right];
  10. if ($sum < 0) {
  11. $left++;
  12. } elseif ($sum > 0) {
  13. $right--;
  14. } else {
  15. $numbers = $arr[$i] . ',' . $arr[$left] . ',' . $arr[$right];
  16. if (!in_array($numbers, $return)) {
  17. $return[] = $numbers;
  18. }
  19. $left++;
  20. $right--;
  21. }
  22. }
  23. }
  24. return $return;
  25. }
  26. $arr = [-10, -9, -8, -4, -2, 0, 1, 2, 3, 4, 5, 6, 9];
  27. var_dump(three_sum($arr));

11.编写一个PHP函数,求任意n个正负整数里面最大的连续和,要求算法时间复杂度尽可能低。

思路:动态规划

  1. /**
  2. * 获取最大的连续和
  3. * @param array $arr
  4. * @return int
  5. */
  6. function max_sum_array($arr)
  7. {
  8. $currSum = 0;
  9. $maxSum = 0;//数组元素全为负的情况,返回最大数
  10. $n = count($arr);
  11. for ($i = 0; $i < $n; $i++) {
  12. if ($currSum >= 0) {
  13. $currSum += $arr[$i];
  14. } else {
  15. $currSum = $arr[$i];
  16. }
  17. }
  18. if ($currSum > $maxSum) {
  19. $maxSum = $currSum;
  20. }
  21. return $maxSum;
  22. }

12. 快速排序算法

时间复杂度:O(NlogN)   稳定性:不稳定

  1. function quickSort($arr) {
  2. $len = count($arr);
  3. if ($len <= 1){
  4. return $arr;
  5. }
  6. $base = $arr[0];
  7. $left = [];
  8. $right = [];
  9. for($i=1;$i < $len;$i++) {
  10. if ($arr[$i] > $base) {
  11. $left[] = $arr[$i];
  12. } else {
  13. $right[] = $arr[$i];
  14. }
  15. }
  16. $left = quickSort($left);
  17. $right = quickSort($right);
  18. return array_merge($left,[$base],$right);
  19. }

13. 冒泡排序

时间复杂度:O(N2)   稳定性:稳定

  1. function bubbleSort($arr) {
  2. $len = count($arr);
  3. if ($len <= 1){
  4. return $arr;
  5. }
  6. for($i = 0;$i < $len -1; $i++) {
  7. for($j = 0;$j < $len -1 - $i;$j++) {
  8. if($arr[$j] > $arr[$j+1]) {
  9. $temp = $arr[$j];
  10. $arr[$j] = $arr[$j + 1];
  11. $arr[$j + 1] = $temp;
  12. }
  13. }
  14. }
  15. }

14. 简单选择排序

时间复杂度:O(n^2) 稳定性:不稳定

  1. function simpleSelectSort($arr){
  2. $len = count($arr);
  3. if($len <= 1){
  4. return $arr;
  5. }
  6. for ($i = 0;$i < $len - 1; $i++) {
  7. $index = $i; //记录当前索引
  8. //遍历当前索引之后的数组,来查找最小值
  9. for ($j = $i + 1; $j < $len; $j ++) {
  10. //如果存在则记录最小值的索引
  11. if ($arr[$index] > $arr[$j]) {
  12. $index = $j;
  13. }
  14. }
  15. //如果是当前索引,则不用交换
  16. if($index != $i) {
  17. $temp = $arr[$index];
  18. $arr[$index] = $arr[$i];
  19. $arr[$i] = $temp;
  20. }
  21. }
  22. return $arr;
  23. }

15. 插入排序

时间复杂度:O(n^2) 空间复杂度:O(1) 稳定性:稳定

  1. //插入排序
  2. function insert_sort($arr) {
  3. //获取数组单元个数
  4. $count = count($arr);
  5. //外层循环用于从未排序区域中取出待排序元素
  6. for ($i=1; $i < $count; $i++) {
  7. //获取当前需要插入已排序区域的元素值
  8. $temp = $arr[$i];
  9. //内层循环用于从已排序区域寻找待排序元素的插入位置
  10. for ($j=$i-1; $j >= 0; $j--) {
  11. //如果$arr[$i]比已排序区域的$arr[$j]小,就后移$arr[$j]
  12. if ($temp < $arr[$j]) {
  13. $arr[$j+1] = $arr[$j];
  14. $arr[$j] = $temp;
  15. } else {
  16. //如果$arr[$i]不小于$arr[$j],则对已排序区无需再排序
  17. break;
  18. }
  19. }
  20. }
  21. return $arr;
  22. }

排序算法与时间复杂度

排序算法与时间复杂度

MySQL 相关题目

事务的实现原理?事务的分类?使用事务应该注意的问题?

事务的实现原理?

事务是基于重做日志文件(redo log)和回滚日志(undo log)实现的。

每提交一个事务必须先将该事务的所有日志写入到重做日志文件进行持久化,数据库就可以通过重做日志来保证事务的原子性和持久性。

每当有修改事务时,还会产生undo log,如果需要回滚,则根据undo log 的反向语句进行逻辑操作,比如insert 一条记录就delete 一条记录。undo log 主要实现数据库的一致性,还可以用来实现MVCC

事务的分类?

事务主要分为:

使用事务应该注意的问题?

说一说drop、delete与truncate的区别?

MySQL的数据库引擎有哪些?有什么区别?

MySQL主要有两个数据库引擎:myisam 和 Innodb.

主要区别如下:

一、表锁差异

MyISAM:

myisam只支持表级锁,用户在操作myisam表时,select,update,delete,insert语句都会给表自动加锁,如果加锁以后的表满足insert并发的情况下,可以在表的尾部插入新的数据。也可以通过lock table命令来锁表,这样操作主要是可以模仿事务,但是消耗非常大,一般只在实验演示中使用。

InnoDB :

Innodb支持事务和行级锁,是innodb的最大特色。

事务的ACID属性:atomicity,consistent,isolation,durable。

并发事务带来的几个问题:更新丢失,脏读,不可重复读,幻读。

事务隔离级别:未提交读(Read uncommitted),已提交读(Read committed),可重复读(Repeatable read),可序列化(Serializable)

四种隔离级别的比较

读数据一致性及并发副作用 隔离级别 读数据一致性 脏读 不可重复读 幻读
为提交读(read uncommitted) 最低级别,不读物理上顺坏的数据
已提交读(read committed) 语句级
可重复读(Repeatable red) 事务级
可序列化(Serializable) 最高级别,事务级

查看mysql的默认事务隔离级别 show global variables like ‘tx_isolation’;.

Innodb的行锁模式有以下几种:共享锁,排他锁,意向共享锁(表锁),意向排他锁(表锁),间隙锁。

注意:当语句没有使用索引,innodb不能确定操作的行,这个时候就使用的意向锁,也就是表锁

关于死锁:

什么是死锁?当两个事务都需要获得对方持有的排他锁才能完成事务,这样就导致了循环锁等待,也就是常见的死锁类型。

解决死锁的方法:

二、数据库文件差异

MyISAM :

myisam属于堆表

myisam在磁盘存储上有三个文件,每个文件名以表名开头,扩展名指出文件类型。

myisam表还支持三种不同的存储格式:

InnoDB :

innodb属于索引组织表

innodb有两种存储方式,共享表空间存储和多表空间存储

两种存储方式的表结构和myisam一样,以表名开头,扩展名是.frm。

如果使用共享表空间,那么所有表的数据文件和索引文件都保存在一个表空间里,一个表空间可以有多个文件,通过innodb_data_file_pathinnodb_data_home_dir参数设置共享表空间的位置和名字,一般共享表空间的名字叫ibdata1-n

如果使用多表空间,那么每个表都有一个表空间文件用于存储每个表的数据和索引,文件名以表名开头,以.ibd为扩展名。

三、索引差异

1、关于自动增长

myisam引擎的自动增长列必须是索引,如果是组合索引,自动增长可以不是第一列,他可以根据前面几列进行排序后递增。

innodb引擎的自动增长列必须是索引,如果是组合索引也必须是组合索引的第一列。

2、关于主键

myisam允许没有任何索引和主键的表存在,

myisam的索引都是保存行的地址。

innodb引擎如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键(用户不可见)

innodb的数据是主索引的一部分,附加索引保存的是主索引的值。

3、关于count()函数

myisam保存有表的总行数,如果select count(*) from table;会直接取出出该值

innodb没有保存表的总行数,如果使用select count(*) from table;就会遍历整个表,消耗相当大,但是在加了wehre条件后,myisam和innodb处理的方式都一样。

4、全文索引

myisam支持 FULLTEXT类型的全文索引

innodb不支持FULLTEXT类型的全文索引,但是innodb可以使用sphinx插件支持全文索引,并且效果更好。(sphinx 是一个开源软件,提供多种语言的API接口,可以优化mysql的各种查询)

5、delete from table

使用这条命令时,innodb不会从新建立表,而是一条一条的删除数据,在innodb上如果要清空保存有大量数据的表,最好不要使用这个命令。(推荐使用truncate table,不过需要用户有drop此表的权限)

6、索引保存位置

myisam的索引以表名+.MYI文件分别保存。

innodb的索引和数据一起保存在表空间里。

InnoDB 四大特性

1.插入缓冲(insert buffer)

插入缓冲(Insert Buffer/Change Buffer):提升插入性能,change buffering是insert buffer的加强,insert buffer只针对insert有效,change buffering对insert、delete、update(delete+insert)、purge都有效

只对于非聚集索引(非唯一)的插入和更新有效,对于每一次的插入不是写到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,如果在则直接插入;若不在,则先放到Insert Buffer 中,再按照一定的频率进行合并操作,再写回disk。这样通常能将多个插入合并到一个操作中,目的还是为了减少随机IO带来性能损耗。

2.二次写(double write)

Doublewrite缓存是位于系统表空间的存储区域,用来缓存InnoDB的数据页从innodb buffer pool中flush之后并写入到数据文件之前,所以当操作系统或者数据库进程在数据页写磁盘的过程中崩溃,Innodb可以在doublewrite缓存中找到数据页的备份而用来执行crash恢复。数据页写入到doublewrite缓存的动作所需要的IO消耗要小于写入到数据文件的消耗,因为此写入操作会以一次大的连续块的方式写入

在应用(apply)重做日志前,用户需要一个页的副本,当写入失效发生时,先通过页的副本来还原该页,再进行重做,这就是double write
doublewrite组成:

对缓冲池的脏页进行刷新时,不是直接写磁盘,而是会通过memcpy()函数将脏页先复制到内存中的doublewrite buffer,之后通过doublewrite 再分两次,每次1M顺序地写入共享表空间的物理磁盘上,在这个过程中,因为doublewrite页是连续的,因此这个过程是顺序写的,开销并不是很大。在完成doublewrite页的写入后,再将doublewrite buffer 中的页写入各个 表空间文件中,此时的写入则是离散的。如果操作系统在将页写入磁盘的过程中发生了崩溃,在恢复过程中,innodb可以从共享表空间中的doublewrite中找到该页的一个副本,将其复制到表空间文件,再应用重做日志。

3.自适应哈希索引(ahi)

Adaptive Hash index属性使得InnoDB更像是内存数据库。该属性通过innodb_adapitve_hash_index开启,也可以通过—skip-innodb_adaptive_hash_index参数
关闭

Innodb存储引擎会监控对表上二级索引的查找,如果发现某二级索引被频繁访问,二级索引成为热数据,建立哈希索引可以带来速度的提升

经常访问的二级索引数据会自动被生成到hash索引里面去(最近连续被访问三次的数据),自适应哈希索引通过缓冲池的B+树构造而来,因此建立的速度很快。

哈希(hash)是一种非常快的等值查找方法,在一般情况下这种查找的时间复杂度为O(1),即一般仅需要一次查找就能定位数据。而B+树的查找次数,取决于B+树的高度,在生产环境中,B+树的高度一般3-4层,故需要3-4次的查询。

4.预读(read ahead)

InnoDB使用两种预读算法来提高I/O性能:线性预读(linear read-ahead)和随机预读(randomread-ahead)
为了区分这两种预读的方式,我们可以把线性预读放到以extent为单位,而随机预读放到以extent中的page为单位。线性预读着眼于将下一个extent提前读取到buffer pool中,而随机预读着眼于将当前extent中的剩余的page提前读取到buffer pool中。

事务是如何通过日志来实现的,说得越深入越好

事务日志是通过redo和innodb的存储引擎日志缓冲(Innodb log buffer)来实现的,当开始一个事务的时候,会记录该事务的lsn(log sequence number)号; 当事务执行时,会往InnoDB存储引擎的日志的日志缓存里面插入事务日志;当事务提交时,必须将存储引擎的日志缓冲写入磁盘(通过innodb_flush_log_at_trx_commit来控制),也就是写数据前,需要先写日志。这种方式称为“预写日志方式”

谈谈数据库优化/复杂sql优化的方法

针对列中的值从左往右建立索引,截的越短,重复度越高区分度越小,所以效果越不好截的越长,区分度越高,索引效果好,但是增删改慢间接影响查询速度,优先考虑在where 和orderby建立索引。

还有其它常见的就

索引的优缺点?那些情况适合建索引那些情况不适合建索引?

索引的优点:

通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。可以大大加快 数据的检索速度,这也是创建索引的最主要的原因。可以加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。在使用分组和排序 子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。通过使用索引,可以在查询的过程中,使用优化隐藏器,提高系统的性能。

索引的缺点

创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大。当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,这样就降低了数据的维护速度。

哪些情况需要加索引?

哪些情况不需要加索引?

对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。

对于那些定义为text, imagebit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。

当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。因此,当修改性能远远大于检索性能时,不应该创建索引。

计算机网络

1.HTTP中GET与POST的区别,注意最后一条

GET在浏览器回退时是无害的,而POST会再次提交请求。
GET产生的URL地址可以被Bookmark,而POST不可以。
GET请求会被浏览器主动cache,而POST不会,除非手动设置。
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留。
GET请求在URL中传送的参数是有长度限制的,而POST没有。
对参数的数据类型,GET只接受ASCII字符,而POST没有限制。
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
GET参数通过URL传递,POST放在Request body中。
GET产生一个TCP数据包,POST产生两个TCP数据包。

2.为什么Tcp连接是三次,挥手是四次

在Tcp连接中,服务端的SYN和ACK向客户端发送是一次性发送的,而在断开连接的过程中,B端向A端发送的ACK和FIN是分两次发送的。因为在B端接收到A端的FIN后,B端可能还有数据要传输,所以先发送ACK,等B端处理完自己的事情后就可以发送FIN断开连接了。

3.Cookie存在哪

如果设置了过期时间,Cookie存在硬盘里
没有设置过期时间,Cookie存在内存里

4.COOKIE和SESSION的区别和关系

COOKIE保存在客户端,而SESSION则保存在服务器端
从安全性来讲,SESSION的安全性更高
从保存内容的类型的角度来讲,COOKIE只保存字符串(及能够自动转换成字符串)
从保存内容的大小来看,COOKIE保存的内容是有限的,比较小,而SESSION基本上没有这个限制
从性能的角度来讲,用SESSION的话,对服务器的压力会更大一些
SEEION依赖于COOKIE,但如果禁用COOKIE,也可以通过url传递

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注