zoukankan      html  css  js  c++  java
  • mysql杂七杂八

    mysql行转列,列转行:

    mysql交集并集差集:

    数据库三范式:

    • 简而言之:1.字段不可再拆分,比如(联系人这样的字段就包含姓名,电话就不行);2.主键必须是一个字段,不能就是多个字段才能确认唯一性;3.一张表中的外键不能是那张表的非主键字段:https://www.cnblogs.com/xiaozengzeng/p/10720226.html

    mysqlclient和pymsql:

    Ubuntu18.04 pip安装mysqlclient时报错MySQLdb/_mysql.c:38:10: fatal error: Python.h: 没有那个文件或目录,解决:

    • 安装mysqlclient 需要安装两个依赖包:

      (1)sudo apt-get install python-dev libmysqlclient-dev # Debian / Ubuntu

      (2)sudo apt-get install python3-dev # Debian / Ubuntu,更多看下面链接

    • https://www.linuxidc.com/Linux/2016-12/138935.htm

    mysql乐观锁和悲观锁的实现:

    mysql中的mvcc的使用

    什么是MVCC 

          MVCC全称是: Multiversion concurrency control,多版本并发控制,提供并发访问数据库时,对事务内读取的到的内存做处理,用来避免写操作堵塞读操作的并发问题。
     
          举个例子,程序员A正在读数据库中某些内容,而程序员B正在给这些内容做修改(假设是在一个事务内修改,大概持续10s左右),A在这10s内 则可能看到一个不一致的数据,在B没有提交前,如何让A能够一直读到的数据都是一致的呢?
     
          有几种处理方法,第一种: 基于锁的并发控制,程序员B开始修改数据时,给这些数据加上锁,程序员A这时再读,就发现读取不了,处于等待情况,只能等B操作完才能读数据,这保证A不会读到一个不一致的数据,但是这个会影响程序的运行效率。还有一种就是:MVCC,每个用户连接数据库时,看到的都是某一特定时刻的数据库快照,在B的事务没有提交之前,A始终读到的是某一特定时刻的数据库快照,不会读到B事务中的数据修改情况,直到B事务提交,才会读取B的修改内容。
          
          一个支持MVCC的数据库,在更新某些数据时,并非使用新数据覆盖旧数据,而是标记旧数据是过时的,同时在其他地方新增一个数据版本。因此,同一份数据有多个版本存储,但只有一个是最新的。
     
          MVCC提供了 时间一致性的 处理思路,在MVCC下读事务时,通常使用一个时间戳或者事务ID来确定访问哪个状态的数据库及哪些版本的数据。读事务跟写事务彼此是隔离开来的,彼此之间不会影响。假设同一份数据,既有读事务访问,又有写事务操作,实际上,写事务会新建一个新的数据版本,而读事务访问的是旧的数据版本,直到写事务提交,读事务才会访问到这个新的数据版本。
     
          MVCC有两种实现方式,第一种实现方式是将数据记录的多个版本保存在数据库中,当这些不同版本数据不再需要时,垃圾收集器回收这些记录。这个方式被PostgreSQL和Firebird/Interbase采用,SQL Server使用的类似机制,所不同的是旧版本数据不是保存在数据库中,而保存在不同于主数据库的另外一个数据库tempdb中。第二种实现方式只在数据库保存最新版本的数据,但是会在使用undo时动态重构旧版本数据,这种方式被Oracle和MySQL/InnoDB使用。
     

    InnoDB的MVCC实现机制

      MVCC可以认为是行级锁的一个变种,它可以在很多情况下避免加锁操作,因此开销更低。MVCC的实现大都都实现了非阻塞的读操作,写操作也只锁定必要的行。InnoDB的MVCC实现,是通过保存数据在某个时间点的快照来实现的。一个事务,不管其执行多长时间,其内部看到的数据是一致的。也就是事务在执行的过程中不会相互影响。下面我们简述一下MVCC在InnoDB中的实现。

      InnoDB的MVCC,通过在每行记录后面保存两个隐藏的列来实现:一个保存了行的创建时间,一个保存行的过期时间(删除时间),当然,这里的时间并不是时间戳,而是系统版本号,每开始一个新的事务,系统版本号就会递增。在RR隔离级别下,MVCC的操作如下:

    1. select操作。
      • InnoDB只查找版本早于(包含等于)当前事务版本的数据行。可以确保事务读取的行,要么是事务开始前就已存在,或者事务自身插入或修改的记录。
      • 行的删除版本要么未定义,要么大于当前事务版本号。可以确保事务读取的行,在事务开始之前未删除。
    2. insert操作。将新插入的行保存当前版本号为行版本号。
    3. delete操作。将删除的行保存当前版本号为删除标识。
    4. update操作。变为insert和delete操作的组合,insert的行保存当前版本号为行版本号,delete则保存当前版本号到原来的行作为删除标识。

      由于旧数据并不真正的删除,所以必须对这些数据进行清理,innodb会开启一个后台线程执行清理工作,具体的规则是将删除版本号小于当前系统版本的行删除,这个过程叫做purge。

    mysql常见函数总结

    sql基本优化方法

    究极面试宝典

    mysql 分页查询的优化方式

    在mysql中limit的偏移量很大时,由于要扫描前面的很多行,所以会导致查询速速比较慢,可以采用下列几种方法

    # 记录上次最大id
    select id, name, content from users where id > 10073 order by id asc limit 20
    
    # 子查询(子查询最好是连续的,order by后面字段要建立索引)
    SELECT * FROM articles WHERE id >= (SELECT id FROM articles WHERE category_id = 123 ORDER BY id LIMIT 10000, 1) LIMIT 10
    
    # join连接
    SELECT * FROM user AS t1 innerjoin (SELECT id FROM user ORDER BY id desc LIMIT ".($page-1)*$pagesize.", 1) AS t2
    WHERE t1.id <= t2.id ORDER BY t1.id desc LIMIT $pagesize;

    创建索引,但无法命中索引的几种情况

    1、应尽量避免在 WHERE 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描。优化器将无法通过索引来确定将要命中的行数,因此需要搜索该表的所有行。(注意,column IS NULL 也是不可以使用索引的。可以在column上设置默认值0,确保column中没有空值)
    
    2、应尽量避免在 WHERE 子句中使用 OR 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,只有or条件全部都是独立索引,才可以用or,如:SELECT id FROM t WHERE num = 10 OR num = 20 可以使用union代替all。
    
    3、应尽量避免在 WHERE 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。
    
    4、应尽量避免在 WHERE 子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
    
    5、不要在 WHERE 子句中的 = 左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。
    
    6、复合索引遵循前缀原则。
    
    7、如果 MySQL 评估使用索引比全表扫描更慢,会放弃使用索引。如果此时想要索引,可以在语句中添加强制索引。
    
    8、列类型是字符串类型,查询时一定要给值加引号,否则索引失效。
    
    9、LIKE 查询,% 不能在前,因为无法使用索引。如果需要模糊匹配,可以使用全文索引。

    复合索引最左匹配原则(最左匹配特性)

    当 B+Tree 的数据项是复合的数据结构,比如索引 (name, age, sex) 的时候,B+Tree 是按照从左到右的顺序来建立搜索树的。

    比如当 (张三, 20, F) 这样的数据来检索的时候,B+Tree 会优先比较 name 来确定下一步的所搜方向,如果 name 相同再依次比较 age 和 sex ,最后得到检索的数据。
    
    但当 (20, F) 这样的没有 name 的数据来的时候,B+Tree 就不知道下一步该查哪个节点,因为建立搜索树的时候 name 就是第一个比较因子,必须要先根据 name 来搜索才能知道下一步去哪里查询。
    
    比如当 (张三, F) 这样的数据来检索时,B+Tree 可以用 name 来指定搜索方向,但下一个字段 age 的缺失,所以只能把名字等于张三的数据都找到,然后再匹配性别是 F 的数据了。

    mysql创建索引的几种方式

    创建表示int(11)中11是什么意思?

    • 表示显示宽度为11,该可选显示宽度规定用于显示宽度小于指定的列宽度的值时从左侧填满宽度。显示宽度并不限制可以在列内保存的值的范围,也不限制超过列的指定宽度的值的显示。也就是说,int的长度并不影响数据的存储精度,长度只和显示有关。

    金额(金钱)相关的数据,选择什么数据类型?

    • 方式一,使用 int 或者 bigint 类型。如果需要存储到分的维度,需要 *100 进行放大。
    • 方式二,使用 decimal 类型,避免精度丢失。如果使用 Java 语言时,需要使用 BigDecimal 进行对应。

    一张表,里面有 ID 自增主键,当 insert 了 17 条记录之后,删除了第 15,16,17 条记录,再把 MySQL 重启,再 insert 一条记录,这条记录的 ID 是 18 还是 15?

    • 一般情况下,我们创建的表的类型是 InnoDB ,如果新增一条记录(不重启 MySQL 的情况下),这条记录的 ID 是18 ;但是如果重启 MySQL 的话,这条记录的 ID 是 15 。因为 InnoDB 表只把自增主键的最大 ID 记录到内存中,所以重启数据库或者对表 OPTIMIZE(mysql对于空记录和索引不会删除,可以使用optimize优化表空间) 操作,都会使最大 ID 丢失。
    • 但是,如果我们使用表的类型是 MyISAM ,那么这条记录的 ID 就是 18 。因为 MyISAM 表会把自增主键的最大 ID 记录到数据文件里面,重启 MYSQL 后,自增主键的最大 ID 也不会丢失。最后,还可以跟面试官装个 x ,生产数据,不建议进行物理删除记录。

     

      

  • 相关阅读:
    2020了,初/中级前端面试你应该知道的(上)
    Vue页面权限控制和动态添加路由
    Javascript获取数组中最大和最小值
    localStorage和cookie的跨域解决方案
    移动端常见问题汇总
    码云git本地仓库链接远程仓库
    IntelliJ IDEA Activation code亲测可用
    Sping4之注入参数
    Sping4之依赖注入
    Spring核心之IOC
  • 原文地址:https://www.cnblogs.com/ycg-blog/p/12609451.html
Copyright © 2011-2022 走看看