MySQL

  • 在过去二十年中,移动互联网飞速发展,催生了大量LBS相关应用,这也让空间信息处理成为较为基础的诉求。PostgreSQL因为其起源就与空间信息处理关系很大,所以在该领域一直有着非常大的优势。MongoDB也在很早就对空间信息处理做了很强的支持,这也帮助MongoDB在发展过程中拿下来部分市场。MariaDB也在去年8月(参考)收购了厂商“CubeWerx”以增强其在地理信息的存储与分析上的能力。

    在过去的十年,MySQL也在不断的增强空间信息的处理能力,本文概述了,当前MySQL在这一块的能力现状。

    当前,数据库访问与处理GIS相关的信息主要参考的是:OGC Standards中的“Simple Feature Access – Part 2: SQL Option”(链接)。当前,MySQL支持的空间类型主要包括:

    • 点、折线、多边形、空间(可以存储前面三种类型中的任何一种)
    • 多点、多折线、多多边形、多空间(可以存储多个任何类型)

    使用MySQL空间类型,则最好使用InnoDB或NDB引擎(其他还支持空间类型的引擎有MyISAM、ARCHIVE),其中InnoDB支持较为完整,对空间索引也有比较好的支持。

    如果要支持地理信息,则可以使用“WGS 84系统”标准的坐标系统,正式名称是:世界大地测量系统(World Geodetic System, WGS),对应的SRID为4326。WGS是当前被广泛使用的地球空间坐标系统,例如GPS就是使用该坐标系统。该坐标系统,建立以地球的质心为中心的一套坐标系统,里面包括地球的一些基础数据等。

    在MySQL可以通过如下Query可以查看MySQL中的WGS 84系统的一些基本信息:

    SELECT *
           FROM INFORMATION_SCHEMA.ST_SPATIAL_REFERENCE_SYSTEMS
           WHERE SRS_ID = 4326\G
    *************************** 1. row ***************************
                    SRS_NAME: WGS 84
                      SRS_ID: 4326
                ORGANIZATION: EPSG
    ORGANIZATION_COORDSYS_ID: 4326
                  DEFINITION: GEOGCS["WGS 84",DATUM["World Geodetic System 1984",
                              SPHEROID["WGS 84",6378137,298.257223563,
                              AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],
                              PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
                              UNIT["degree",0.017453292519943278,
                              AUTHORITY["EPSG","9122"]],
                              AXIS["Lat",NORTH],AXIS["Long",EAST],
                              AUTHORITY["EPSG","4326"]]
                 DESCRIPTION:

    基础对象和对应的WKT表达

    MySQL或者说SQL标准中支持的对象包括如下,:Point、Linestring、Polygon、Multi Point、Multi Linestring、Multi Polygon、Geometry Collection。

    具体的:

    • Point、LineSting都比较好理解
      • 在WKT表达中,点的X/Y坐标,之间并没有逗号;但是,MySQL的Point函数,则是需要逗号的。
      • 这里省略了一个叫“LineRing”的概念,LineRing就是一个不相交且头尾相连的LineString
    • Polygon有两种,一种是普通的,一种是带hole的Polygon
    • Polygon是一个Surface,不仅仅是组成边缘的点,还包含内部覆盖区域
    • Polygon即便是普通的(不带hole),外部也会有一个括号
    • Polygon通常是由多个LineRing组成

    在这个规范下,就可以非常简单的创建OGC标准中的对象,例如:

    CREATE TABLE geom (
        id int,
        p POINT SRID 0
    );
    
    INSERT INTO geom(id,p) values (1,Point(12,30));

    在实际查询中,默认的空间类型会返回二进制类型数据,所以客户端查询需要进行一次转换,将其转换容易阅读的文本类型,即标准的WKT(Well-Known Text):

    转化前:

    mysql> select * from geom;
    +------+---------------------------+
    | id   | p                         |
    +------+---------------------------+
    |    1 |              (@      >@ |
    +------+---------------------------+
    1 row in set (0.00 sec)

    使用了WKT函数转换后:

    mysql> select id,ST_AsText(p) from geom;
    +------+--------------+
    | id   | ST_AsText(p) |
    +------+--------------+
    |    1 | POINT(12 30) |
    +------+--------------+

    好的,这是一个简单的入门介绍,更多的能力需要自己探索,祝玩得开心。

  • 使用MySQL的函数索引

    ·

    从MySQL 8.0.13起,开始支持函数索引功能,该功能可以很好的帮助开发人员或者DBA去优先生产环境的SQL语句。通常,我们是并建议在SQL语句的查询条件中对列进行任何的函数计算的,因为这种做很有可能导致原本可以使用索引的查询条件,变得无法使用索引。

    例如,我们看如下的查询条件:

    SELECT * FROM user_info WHERE substr(id_card_no,1,6) = '330106';

    虽然,该表的id_card_no上原本是存在索引的,但是上面的写法则会导致SQL无法正常使用id_card_no列上的索引。一般来说,我们会建议开发人员,避免这种写法,更多的是将表达式放到右侧,如上的SQL则建议修改为:

    SELECT * FROM user_info WHERE id_card_no like '330106%';

    但某些情况下,我们可能无法修改SQL,例如:

    • 有很多的函数计算或表达式操作并不能简单的转换到表达式的右边,例如:uid%1024 = 7
    • 应用程序来自第三方,而我们并不拥有第三方的代码,也无法进行修改SQL
    • 生产故障已经由此产生,可能来不及修改线上的代码或SQL
    • 还有一个略微“牵强”的说法:SQL语法更加注重解释性,并不关注实现,基于此大原则,上面的SQL写法并没有什么问题。

    函数索引使用示例

    MySQL的函数索引是8.0版本引入的重要特性之一。它允许开发人员在查询中使用函数,并且依旧可以有效地加速查询性能。具体的,函数索引的作用是通过在函数表达式上创建索引,在处理字符串、日期、数值等类型的数据时特别有用。

    (more…)
  • 近期,据可靠的非正式消息,MySQL可能很快会发布新的版本管理模式:通过长期稳定版(Long-term Support)和短期创新版本(Innovation Releases)的方式进行管理。如果采用这种模式,将会更加有利于新特性新功能的引入,同时保持LTS的长期处于较稳定的状态(可以参考ClickHouse的版本管理现状),缺点则是版本会非常多,对新手不是那么友好。另外,因为MySQL 5.7的生命周期将于今年10月正式结束,如果届时依旧没有新的版本的话,MySQL 8.0就会是唯一的稳定版,通常对于快速发展的开源软件来说,这并不健康。所以,前述的消息虽然是非正式的,但是相信是非常可靠的。那么新的版本是号会是8.1、9.0、或者23、2023,拭目以待”。

    本文总结了过去20年,MySQL的版本发展历史,回顾一下其重大功能发布的情况,以及大版本发布的节奏。

    (more…)
  • MySQL的不可见索引

    ·

    不可见索引(Invisible Indexes)MySQL 8.0之后引入的一个重要特性。也可以帮助DBA或者开发者更好的管理和维护数据库的索引。本文将介绍不可见索引的一些常见使用场景和注意事项。

    更加安全的删除没用的索引

    通常,线上运行时间较长的系统,可以通过索引使用统计信息知道哪些索引是从来不被使用的,但依旧会占用磁盘空间,并且会影响系统的写入/更新/删除操作的性能。但是删除索引的操作,有时候也会带来意想不到的系统性能下降,所以,在正式删除之前,可以先将索引修改为不可用,待观察数日后再进行删除,会更加安全。

    性能分析

    有时候在对线上系统进行SQL性能分析时,有时候为了排除某些索引对查询性能影响时,可以暂时的将某些索引暂时标记为不可用,再统计此时的SQL执行时长与性能。然后,再将索引置为可见,再次执行SQL,并统计执行时长与性能。

    通过这样对比,可以非常简单直观、量化的观察到索引对对于具体SQL性能的提升。

    不可见索引依旧会有维护成本

    虽然不可见索引不会被查询优化器使用,但在对数据进行DML操作(如:插入、更新、删除)时仍会被维护。这意味着不可见索引可能会对数据库性能产生一定影响。在使用不可见索引进行性能测试或分析时,请务必权衡这一点。

    不建议长期保留不可见索引

    如果确定某个不可见索引对查询性能没有帮助,建议尽早删除该索引,以节省存储空间和减小维护成本。否则,该索引对系统性能没有起到任何正面作用,反而会占用空间,并影响DML的性能。

    优化器选项可以让不可见索引生效

    在优化器选项(optimizer_switch)中,可以通过打开标记位(use_invisible_indexes),来强制优化器忽略索引的不可见属性,这在增加了SQL性能调试时的灵活性。

    可以通过SELECT/SHOW命令查询优化器选项,也可用通过SET命令变更该选项:

    SET [GLOBAL|SESSION] optimizer_switch='command[,command]...';
    
    SET SESSION optimizer_switch = 'use_invisible_indexes=ON';
  • 在日常编写SQL中,使用变量来灵活的构建执行的SQL语句是比较常见的。就像在编程中使用变量、函数参数等是一样的道理。本文介绍使用JSON函数(JSON_ARRAYJSON_SEARCH)、以及 FIND_IN_SET 如何简单的实现带有数据组变量的SQL拼接与执行。使用该方法,则无需使用CONCAT函数拼接SQL,再使用PREPARE/EXECUTE语法执行,所以会更加简洁,可读性、扩展性更强。

    具体的,例如需要再查询结果中找到u_name在数组@u_list_j中的记录,那么使用JSON方式可以按照如下模式实现:

    SET @u_list_j = JSON_ARRAY('zhou','wu','zheng','wang','zhuge');
    
    SELECT 
        id,u_name 
    FROM 
        t_01 
    WHERE 
        JSON_SEARCH(@u_list_j,'one',t_01.u_name);

    另一种较为常见的方法是使用 FIND_IN_SET 函数。其使用方法如下:

    set @u_list_s = 'zhou,wu,zheng,wang,zhuge';
    
    SELECT 
        u_name 
    FROM 
        t_01 
    WHERE 
        FIND_IN_SET(t_01.u_name,@u_list_s);

    另外,还可以尝试使用 LOCATE 函数实现,只是使用该函数需要注意,在做字符串匹配的时候容易出现的重复、错误匹配问题。例如,数组中存在”zhuge”,那么匹配”zhu”,则可能匹配成功,但这并不是期望的结果。

    示例表:

    本文中使用的一些示例表如下:

    CREATE TABLE t_01(
      id int UNSIGNED AUTO_INCREMENT primary key,
      u_name varchar(32)
    );
    
    INSERT INTO t_01(u_name) values
      ('wu'),
      ('zhao'),
      ('qian'),
      ('sun'),
      ('li');
  • 如何学习MySQL

    ·

    《高性能MySQL》第四版发布后,收到了很多读者的反馈,其中关注最多的是作为一个初学者,应该如何能够较为系统的学习MySQL,从而应对日常工作或者获得更好的职业发展。于是和多个业内朋友讨论后,整理了一些MySQL学习的推荐资源,供初学者参考。文章末尾有一个MySQL学习交流群,供加入提问与讨论。


    业界专家的经验

    Yangyidba 阿里云的数据库专家

    yangyidba 阿里云数据库专家

    刚刚入行时,有哪些资料给你了帮助?

    正式接触 MySQL 是2011年底,当时的公司的数据库版本主要是 5.5 版本和少量 5.1 版本。因为之前学Oracle的经验是查看官方文档,学习MySQL 资料主要是 “官方文档” 和当时的淘宝DBA团队组织的技术大学的技术分享,学习MySQL技术的技术特性和经典案例。

    其实就现在而言,MySQL 官方文档依然是最好的学习资料和教材, 里面非常详细的说明 MySQL的基础架构,redo,undo,读写逻辑,字段类型,锁,存储引擎,主从复制,MGR ,性能优化等等。把官方文档通读一遍,基本上能超越60-70%左右的DBA,为什么不是更高呢?因为学习技术是为了使用技能。

    进一步了解 MySQL/数据库,是哪些资料帮助了你?

    (more…)