大家好,今天给大家上3个经典的MySQL问题,希望能对大家有帮助!但是因为笔者计算机水平有限,可能会存在一些错误,烦请指出、斧正!谢谢!

  • 一、在MySQL中INNER JOIN、LEFT JOIN、RIGHT JOIN 和 FULL JOIN 有什么区别?
  • 二、你会推荐使用 datetime 还是 timestamp 字段?为什么?
  • 三、MyISAM 与 InnoDB,什么场景选择哪一个?

一、在MySQL中INNER JOIN、LEFT JOIN、RIGHT JOIN 和 FULL JOIN 有什么区别?

我们有两张表:

  1.  
    TableA:
  2.  
    id firstName                 lastName
  3.  
    .......................................
  4.  
    1   arun                       prasanth                
  5.  
    2   ann                         antony                  
  6.  
    3   sruthy                     abc                      
  7.  
    6   new                         abc                                          
  8.  
    复制代码
  1.  
    TableB:
  2.  
    id2 age Place
  3.  
    ................
  4.  
    1   24 kerala
  5.  
    2   24 usa
  6.  
    3   25 ekm
  7.  
    5   24 chennai
  8.  
    复制代码

1. INNER JOIN(内连接)

这是最简单,最常见,也是最容易理解的Join,两张表使用内连接查询时,得到的结果是两张表中完全匹配的行集。

对于上述两张表,我们有:

  1.  
    SELECT TableA.firstName,TableA.lastName,TableB.age,TableB.Place
  2.  
    FROM TableA
  3.  
    INNER JOIN TableB
  4.  
      ON TableA.id = TableB.id2;
  5.  
    复制代码

得到的结果即为:

  1.  
    firstName       lastName       age Place
  2.  
    ..............................................
  3.  
    arun           prasanth       24 kerala
  4.  
    ann             antony         24 usa
  5.  
    sruthy         abc             25 ekm
  6.  
    复制代码

得到的结果有4个字段,firstName 、 lastName 、 age 、 Place,就是我们上面SQL语句SELECT的4个字段,FROM和INNER JOIN后面的两个表名就是要内连接的两张表,ON后面就是在其中寻找共同点的字段。

2. LEFT JOIN(左连接)

左连接查询会返回左表中所有行,无论这些行是不是有任何一行在右表中匹配。

  1.  
    SELECT TableA.firstName,TableA.lastName,TableB.age,TableB.Place
  2.  
    FROM TableA
  3.  
    LEFT JOIN TableB
  4.  
      ON TableA.id = TableB.id2;
  5.  
    复制代码

查询结果是:

  1.  
    firstName               lastName                 age   Place
  2.  
    .............................................................
  3.  
    arun                     prasanth                 24   kerala
  4.  
    ann                     antony                   24   usa
  5.  
    sruthy                   abc                     25   ekm
  6.  
    new                     abc                     NULL NULL
  7.  
    复制代码

我们可以看到,TableA中所有行都过来了,即使firstName为new,lastName为abc的那一行id为6,在TableB中找不到id为6的行,仍然在结果集中存在。值得注意的是,因为其id为6,在TableB中找不到对应的id,因此其没有age和Place字段的内容。

3. RIGHT JOIN(右连接)

右连接查询会返回右表中所有行,无论这些行是不是有任何一行在左表中匹配。

  1.  
    SELECT TableA.firstName,TableA.lastName,TableB.age,TableB.Place
  2.  
     FROM TableA
  3.  
    RIGHT JOIN TableB
  4.  
       ON TableA.id = TableB.id2;
  5.  
    复制代码

结果集:

  1.  
    firstName               lastName               age     Place
  2.  
    ...............................................................
  3.  
    arun                     prasanth               24     kerala
  4.  
    ann                     antony                 24     usa
  5.  
    sruthy                   abc                    25     ekm
  6.  
    NULL                     NULL                   24     chennai
  7.  
    复制代码

4. FULL JOIN(全连接)

SQL语句如下:

  1.  
    SELECT TableA.firstName,TableA.lastName,TableB.age,TableB.Place
  2.  
    FROM TableA
  3.  
    FULL JOIN TableB
  4.  
    ON TableA.id = TableB.id2;
  5.  
    复制代码

结果集为:

  1.  
    firstName lastName age Place
  2.  
    ...........................................................
  3.  
    arun prasanth 24 kerala
  4.  
    ann antony 24 usa
  5.  
    sruthy abc 25 ekm
  6.  
    new abc NULL NULL
  7.  
    NULL NULL 24 chennai
  8.  
    复制代码

查询结果是左连接和右连接的并集。

二、你会推荐使用 datetime 还是 timestamp 字段?为什么?

  1. 正如Mysql文档描述的那样——datetime的范围是“1000-01-01 00:00:00”到“9999-12-31 23:59:59”,而timestamp的范围是 '1970-01-01 00:00:01' UTC 到 '2038-01-09 03:14:07' UTC。如果不想程序在2038年出问题,从这个方面作者建议还是使用datetime。

  2. 有一种观点是既不使用 DATETIME 也不使用 TIMESTAMP 字段。如果想将特定的一天作为一个整体来表示(例如生日),可以使用 DATE 类型,但是如果需要更具体的时间,不要使用 DATETIME 或 TIMESTAMP,而是使用 BIGINT,并简单地存储自纪元以来的毫秒数(如果使用的是 Java,则为 System.currentTimeMillis())。

    这样有几个优点。其一,可以在迁移数据库时避免因为数据类型差异,比如MySQL的DATETIME类型和Oracle的DATETIME类型之间可能存在差异,timestamp类型的精度可能也存在差异,MySQL的timestamp精度不是一开始就支持毫秒精度的。其二,没有时区问题,无论是哪个时区,因为开始计算的时间不同,无论当前时间如何,跨度是一致的。其三,没有timestamp和datatime的范围问题,哪怕是datatime,8000年以后也不能用了,没准我的数据库8000年能用8000年呢。

  3. 需要注意的是,bigint是占用8个字节,而timestamp只占用4个字节。从MySQL 5.6.4开始,Datetime的存储空间变成了5个字节了(准确的说应该是5字节+0~3个字节的FSP分秒精度)。

三、MyISAM 与 InnoDB,什么场景选择哪一个?

MyISAM 和 InnoDB 之间的主要区别在于参照完整性和事务。还有其他区别,例如锁定、回滚和全文搜索。

参照完整性

参照完整性确保表之间的关系保持一致。更具体地说,当一个表(例如 Listings)有一个外键(例如 Product ID)指向另一个表(例如 Products)时,当指向的表发生更新或删除时,这些更改会级联到链接的表。在该示例中,如果重命名产品,则链接的表的外键也会更新;如果从Products表中删除产品,则指向已删除条目的 Listings 表中得到任何列表也将被删除。此外,任何 Listings 表中的新列表都必须具有指向有效的现有条目的外键。

InnoDB 是一个关系型 DBMS (RDBMS),因此具有参照完整性,而 MyISAM 则没有。

事务和原子性

使用数据操作语言 (DML) 语句管理表中的数据,例如 SELECT、INSERT、UPDATE 和 DELETE。事务将两个或多个 DML 语句组合成一个工作单元,因此要么应用整个单元,要么不应用。

MyISAM 不支持事务,而 InnoDB 支持。

如果在使用 MyISAM 表时操作被中断,该操作将立即中止,并且受影响的行(甚至每行中的数据)仍然受到影响,即使该操作没有完成。

如果一个操作在使用 InnoDB 表时被中断,因为它使用具有原子性的事务,任何没有完成的事务都不会生效,因为没有提交。

表锁定与行锁定

当查询 MyISAM 表时,正在查询的整个表将被锁定。这意味着后续查询将仅在当前查询完成后才能执行。如果您正在读取一个大表,并且有频繁的读写操作,这可能意味着大量的查询积压。

而当查询 InnoDB 表时,只有涉及的行被锁定,表的其余部分仍然可进行 CRUD 操作。这意味着查询可以在同一个表上同时运行,只要它们不使用同一行。

InnoDB 中的此功能称为并发。尽管并发性很好,但在表的范围查询时有一个缺点,因为在内核线程之间切换存在开销,我们应该对内核线程设置限制以防止服务器停止。

事务和回滚

当在 MyISAM 中执行一个操作时,更改会立刻生效;在 InnoDB 中,这些更改可以回滚。用于控制事务的最常用命令是 COMMIT、ROLLBACK 和 SAVEPOINT。

  1. COMMIT - 您可以编写多个 DML 操作,但只有在进行 COMMIT 时才会保存更改
  2. ROLLBACK - 您可以丢弃任何尚未提交的操作
  3. SAVEPOINT - 实现回滚到指定保存点

可靠性

MyISAM 不提供数据完整性——硬件故障、不正常的关机操作都可能导致数据损坏。这将需要修复或重建索引和表。

而InnoDB 使用事务日志、双写缓冲区和自动校验和和验证来防止数据损坏。在 InnoDB 进行任何更改之前,它会将事务之前的数据记录到一个名为 ibdata1 的系统表空间文件中。如果发生崩溃,InnoDB 将通过这些日志来自动恢复。

全文索引

InnoDB 在 MySQL 5.6.4 版本之前不支持 FULLTEXT 索引。

但是,这不是使用 MyISAM 的理由。最好使用最新版本的 MySQL 。并不是说使用 FULLTEXT 索引的 MyISAM 表不能转换为 InnoDB 表。

结论

总之,InnoDB 应该是我们默认的存储引擎。在有特定需求时可以选择 MyISAM 或其他数据类型。

三个经典的MySQL问题的更多相关文章

  1. 微服务实战(三):以MySQL为例,从原理上理解那些所谓的数据库军规

    原文链接:微服务化的数据库设计与读写分离(来源:刘超的通俗云计算) 数据库永远是应用最关键的一环,同时越到高并发阶段,数据库往往成为瓶颈,如果数据库表和索引不在一开始就进行良好的设计,则后期数据库横向 ...

  2. 阿里云服务器Linux CentOS安装配置(三)yum安装mysql

    阿里云服务器Linux CentOS安装配置(三)yum安装mysql 1.执行yum安装mysql命令:yum -y install mysql-server mysql-devel 2.启动mys ...

  3. 三招搞挂Mysql(转)

    一.产生大量的undo日志 众所周知,InnoDB是一个支持MVCC的存储引擎,为了支持MVCC,InnoDB需要保存undo日志,以便对用户提供记录的历史版本.如果我们开启一个事务,反复地更新一条记 ...

  4. 【转】进程同步之信号量机制(pv操作)及三个经典同步问题

    原文地址:http://blog.csdn.net/speedme/article/details/17597373 上篇博客中(进程同步之临界区域问题及Peterson算法),我们对临界区,临界资源 ...

  5. LIS(最长上升子序列)的三种经典求法

    求最长上升子序列的三种经典方案: 给定一个长度为 \(N\) 的数列,求它数值单调递增的子序列长度最大为多少.即已知有数列 \(A\) , \(A=\{A_1,A_2....A_n\}\) ,求 \( ...

  6. 经典书籍---MySQL经典书籍下载

    以下是一些经典的MySQL书籍电子版,括号内为提取码,若需自取. 欢迎阅读纸质版,尊重作者版权 高性能MySQL_中文版 [ hre3 ] 高性能MySQL_英文版[ m2xj ] MySQL技术内幕 ...

  7. 三种方法查看MySQL数据库的版本

    1.使用-V参数 首先我们想到的肯定就是查看版本号的参数命令,参数为-V(大写字母)或者--version 使用方法: D:\xampp\mysql\bin>mysql -V 或者 D:\xam ...

  8. 14款经典的MySQL客户端软件

    1. EMS MySQL Manager 强大的mysql管理工具,允许用户通过图形界面创建或编辑数据库对象,并提供通过sql语句管理用户和权限,通过图形界面建立sql语句,自动生成html格式的数据 ...

  9. JavaEE系列之(三)JDBC操作MySQL数据库

    一.JDBC简介        JDBC(Java Data Base Connectivity)java数据库连接        SUN公司为了简化.统一对数据库的操作,定义了一套Java操作数据库 ...

  10. 三白话经典算法系列 Shell排序实现

    山是包插入的精髓排序排序,这种方法,也被称为窄增量排序.因为DL.Shell至1959提出命名. 该方法的基本思想是:先将整个待排元素序列切割成若干个子序列(由相隔某个"增量"的元 ...

随机推荐

  1. 「SOL」Hamiltonian Cycle (AtCoder)

    原来一般的四度图也没法快速构造哈密顿回路 QwQ # 题面 给定质数 \(P\) 和正整数 \(a,b\),构造一个长为 \(P\) 的数列 \(G=(g_1,g_2,\dots,g_P)\),满足: ...

  2. Delphi中纤程的使用

    首先我们来看看纤程的定义 纤程(来自百科): 纤程是Windows为了将Unix服务程序更好的移植到Windows上而创建的, 线程是在Windows内核中实现的,纤程是在用户模式下实现的,内核对纤程 ...

  3. S32DS中链接文件及启动代码学习

    S32DS中链接文件及启动代码学习 一.链接文件 <Linker Files>文件夹中有linker_flash.ld文件和linker_ram.ld文件. Linker File称为链接 ...

  4. echo 操作

    echo打印制表符到文件: MAP_PATH=/path/for i in `cat sp.list`; do echo -e "${MAP_PATH}/${i}.${i}/${i}.fin ...

  5. js 基础篇--保留字

    1.js把一些标识符拿出来用作自己的关键字.因此,就不能再在程序中把这些关键字用作标识符了: 1 break delete function return typeof 2 case do if sw ...

  6. ES6的Map和Set的了解和练习

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. 【LeetCode - 1055】形成字符串的最短路径

    1.题目描述 代码: #include <iostream> #include <string> using namespace std; const int MAX_LETT ...

  8. CVPixelBufferRef

    在iOS里,我们经常能看到 CVPixelBufferRef 这个类型,在Camera 采集返回的数据里得到一个CMSampleBufferRef,而每个CMSampleBufferRef里则包含一个 ...

  9. macOS开发应用Sign(签名)和Notarizaiton(公证)

    签名 可执行文件签名: codesign -f -s ${证书ID} --timestamp ${签名文件} .Pkg安装文件签名: productsign --timestamp --sign ${ ...

  10. 打开CMD的方式

    打开Cmd的方式: 1.开始+系统+命令提示符 2.Win键+R 3.在任意文件夹下,按住Shift键+鼠标右键点击,在此处打开命令行窗口 4.资源管理的地址栏前面加上Cmd路径 管理员运行方式 :系 ...