首頁  >  文章  >  資料庫  >  mysql ft指的是什麼

mysql ft指的是什麼

PHPz
PHPz轉載
2023-04-14 17:42:031541瀏覽

mysql ft指的是FullText,即全文索引;全文索引是為了解決需要基於相似度的查詢,而不是精確數值比較;全文索引在大量的數據面前,能比like快N倍,速度不是一個數量級。

MySQL 全文索引(FullText)

#一、簡介

基本概念

全文索引是為了解決需要基於相似度的查詢,而不是精確數值比較。

雖然使用 like % 也可以實現模糊匹配,但是對於大量的文字資料檢索,是不可想像的。全文索引在大量的資料面前,能比 like 快 N 倍,速度不是一個數量級。

版本支援

  1. MySQL 5.6 先前的版本,只有MyISAM 儲存引擎支援全文索引

  2. #MySQL 5.6 及以後的版本,MyISAMInnoDB 儲存引擎都支援全文索引

  3. #MySQL 5.7.6 中,提供了支援中文、日文和韓文(CJK)的內建全文ngram 解析器,以及用於日文的可安裝MeCab 全文解析器外掛程式

  4. 全文索引只能用於InnoDBMyISAM表,只能為CHARVARCHARTEXT列建立

  5. #對於大型資料集,e2a5cfc322b0fffd61a8c4e2ec9a2d2b將資料載入到沒有全文索引的表中然後建立索引要比將資料載入到具有現有全文索引的表中快得多

  6. RDS MySQL 5.6 雖然也支援中文全文檢索,但存在BUG

限制與缺點

  • #導致磁碟資源的大量佔用。全文索引本身就是一個利用磁碟空間換取效能的方法。全文索引大的原因是,按照某種語言來進行分詞

  • 全文索引創建速度慢,而且對有全文索引的各種資料修改操作也慢

  • #使用全文索引並不是對應用程式透明的。如果要利用全文索引,必須修改查詢語句。原有的查詢語句是不可能利用全文索引的,需要改成全文索引規定的語法

  • #不區分大小寫

  • 分區表格不支援全文搜尋

  • 由多列組合而成的全文檢索的索引必須使用相同的字元集與排序規則

  • 全文索引可能存在精度問題,即全文索引找到的數據,可能和like到的不一致

  • MATCH()函數中的列必須與FULLTEXT索引中定義的列完全一致,除非是在MyISAM表中使用IN BOOLEAN MODE模式的全文搜索(可在沒有建立索引的列執行搜索,但速度很慢)

  • #單列分別建立全文索引時,多列模糊查詢時不生效

  • 不同表的全文索引不能放在一起查詢,可以兩個語句中加上OR

二、操作全文索引

2.1 配置最小搜尋長度

我們可以透過SQL 指令查看目前配置的最小搜尋長度(分詞長度):

SHOW VARIABLES LIKE 'ft%';
Variable_name Value
ft_boolean_syntax -> ;c50b7bfcb9656106990b53b4f50d6846” 表示出现该单词时增加相关性,查询的结果靠前
  • “<” 表示出现该单词时降低相关性,查询的结果靠后

  • * 表示通配符,只能接在词后面

  • ~ 允许出现该单词,但是出现时相关性为负,表示拥有该字会下降相关性,但不像「-」将之排除,只是排在较后面

  • "" 双引号表示短语,表示要彻底相符,不可拆字效果,类同于 like '%keyword%'

  • () 经过括号来使用字条件:

  • +aaa +(>bbb <ccc) aaa="aaa" sql="sql" select="select" from="from" test="test" where="where" match="match" against="against" in="in" boolean="boolean" mode="mode" select="select" from="from" tommy="tommy" where="where" match="match" against="against" in="in" boolean="boolean" mode="mode" select="select" from="from" tommy="tommy" where="where" match="match" against="against">李秀琴 <练习册 <不是人>是个鬼&#39; in boolean mode);

    四、测试结果

    测试环境:本机4核16G Windows10,MySQL 8.0
    测试数据量salebilldetail1276万行,salebill269 万行, customer30 万行, goods75 万行。

    争对测试用的SQL语句,增加了以下全文索引:

    CREATE FULLTEXT INDEX billno_fulltext ON salebill(billno) WITH PARSER ngram;
    CREATE FULLTEXT INDEX remarks_fulltext ON salebill(remarks) WITH PARSER ngram;
    CREATE FULLTEXT INDEX remarks_fulltext ON salebilldetail(remarks) WITH PARSER ngram;
    CREATE FULLTEXT INDEX goodsremarks_fulltext ON salebilldetail(goodsremarks) WITH PARSER ngram;
    CREATE FULLTEXT INDEX remarks_goodsremarks_fulltext ON salebilldetail(remarks, goodsremarks) WITH PARSER ngram;
    CREATE FULLTEXT INDEX custname_fulltext ON customer(custname) WITH PARSER ngram;
    CREATE FULLTEXT INDEX goodsname_fulltext ON goods(goodsname) WITH PARSER ngram;
    CREATE FULLTEXT INDEX goodscode_fulltext ON goods(goodscode) WITH PARSER ngram;

    测试结果,总的来说很魔幻。
    为什么魔幻,看下面几个语句:

    test_1
    -- 测试1,原始 like 查询方式,用时 0.765s
    select 1 from salebilldetail d where d.tid=260434 and ((d.remarks like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;)) or (d.goodsremarks like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;)));
    test_2
    -- 测试2,使用全文索引 remarks_fulltext、goodsremarks_fulltext, 用时 0.834s
    select 1 from salebilldetail d where d.tid=260434 and ((match(d.remarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)) or (match(d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;)  in boolean mode)));
    test_3
    -- 测试3,使用全文索引 remarks_goodsremarks_fulltext, 用时 0.242s
    select 1 from salebilldetail d where d.tid=260434 and ((match(d.remarks,d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)));
    test_4
    -- 测试4,原始 like 查询方式,不过滤 tid ,用时 22.654s
    select t from salebilldetail d where ((d.remarks like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;)) or (d.goodsremarks like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;)));
    test_5
    -- 测试5,使用全文索引 remarks_fulltext、goodsremarks_fulltext,  不过滤 tid ,用时 24.855s
    select 1 from salebilldetail d where ((match(d.remarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)) or (match(d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;)  in boolean mode)));
    test_6
    -- 测试6,使用全文索引 remarks_goodsremarks_fulltext, 不过滤 tid ,用时 0.213s
    select 1 from salebilldetail d where ((match(d.remarks,d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)));
    test_7
    -- 测试7,使用全文索引 remarks_goodsremarks_fulltext, 用时 0.22s
    select count(1) from salebilldetail d where d.tid=260434 and  ((match(d.remarks,d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)));
    test_8
    -- 测试8,使用全文索引 remarks_goodsremarks_fulltext, 不过滤 tid ,用时 0.007s
    select count(1) from salebilldetail d where ((match(d.remarks,d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)));

    从上面的测试语句可以看出,数据量越多,查询越简单,全文索引的效果越好

    再来看看我们的业务测试SQL:

    test_9
    -- 测试9
    select 
        i.billid
        ,if(0,0,i.qty) as qty  
        ,if(0,0,i.goodstotal) as total          
        ,if(0,0,i.chktotal) as selfchktotal   
        ,if(0,0,i.distotal) as distotal 
        ,if(0,0,i.otherpay) as feetotal  
        ,if(0,0,ifnull(d.costtotal,0)) as costtotal  
        ,if(0,0,ifnull(d.maoli,0)) as maoli         
        ,i.billno
        ,from_unixtime(i.billdate,&#39;%Y-%m-%d&#39;) as billdate /*单据日期*/
        ,from_unixtime(i.createdate,&#39;%Y-%m-%d %H:%i:%s&#39;) as createdate /*制单日期*/
        ,if(i.sdate=0,&#39;&#39;,from_unixtime(i.sdate,&#39;%Y-%m-%d  %H:%i:%s&#39;)) as sdate /*过账日期*/
        ,from_unixtime(i.udate,&#39;%Y-%m-%d %H:%i:%s&#39;) as udate /*最后修改时间*/
        ,i.custid ,c.custname
        ,i.storeid ,k.storename
        ,i.empid ,e.empname
        ,i.userid ,u.username
        ,i.remarks                               /*单据备注*/
        ,i.effect,i.settle,i.redold,i.rednew     /*单据状态*/
        ,i.printtimes /* 打印次数 */
        ,(case  when i.rednew=1 then 1  when i.redold=1 then 2  when i.settle=1 then 3  when i.effect=1 then 4  else 9 end) as state /*单据状态*/
        ,(case  when i.rednew=1 then &#39;红冲单&#39;  when i.redold=1 then &#39;已红冲&#39;  when i.settle=1 then &#39;已结算&#39;  when i.effect=1 then &#39;已过账&#39;  else &#39;草稿&#39; end) as statetext
        ,&#39;&#39; as susername /* 操作人 */
        ,&#39;&#39; as accname /* 科目 */
    from salebill i
    left join coursecentersale d on d.tid=i.tid and d.billid=i.billid
    left join customer c on c.tid=i.tid and c.custid=i.custid
    left join store k on k.tid=i.tid and k.storeid=i.storeid
    left join employee e on e.tid=i.tid and e.empid=i.empid
    left join user u on u.tid=i.tid and u.userid=i.userid
    where i.tid=260434 and (i.billtype = 5 or i.effect = 1)
        and (&#39;_billdate_f_&#39;!=&#39;&#39;)
        and (&#39;_billdate_t_&#39;!=&#39;&#39;)
        and (&#39;_sdate_f_&#39;!=&#39;&#39;)
        and (&#39;_sdate_t_&#39;!=&#39;&#39;)
        and (&#39;_udate_f_&#39;!=&#39;&#39;)
        and (&#39;_udate_t_&#39;!=&#39;&#39;)
        and (&#39;_cdate_f_&#39;!=&#39;&#39;)
        and (&#39;_cdate_t_&#39;!=&#39;&#39;)
        and (&#39;_billid_&#39;!=&#39;&#39;)      /*单据id*/
        and (&#39;_custid_&#39;!=&#39;&#39;)      /*客户ID*/
        and (&#39;_storeid_&#39;!=&#39;&#39;)     /*店仓ID*/
        and (&#39;_empid_&#39;!=&#39;&#39;)       /*业务员ID*/
        and (&#39;_custstop_&#39;!=&#39;&#39;)       /*客户是否停用*/
        and (
            (i.billno like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;))
            or (i.remarks like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;))
            or exists(select 1 from salebilldetail d where d.tid=260434 and d.billid=i.billid and ((d.remarks like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;)) or (d.goodsremarks like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;))))
            or exists(select 1 from customer c where c.tid=260434 and c.custid=i.custid and (c.custname like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;)))
            or exists(select 1 from goods g join salebilldetail d on d.tid=g.tid and d.goodsid=g.goodsid where d.tid=260434 and d.billid=i.billid and ((g.goodsname like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;)) or (g.goodscode like concat(&#39;%&#39;,&#39;葡萄&#39;,&#39;%&#39;))))
        )
        and i.rednew=0 /*单据列表不含红冲单*/ 
        and i.billid not in (select billid from coursecenter_del t where t.tid=260434)
        and ((i.settle=1 and i.effect=1 and i.redold=0 and i.rednew=0)) /*已结算*/
    order by udate desc,billno desc
    limit 0,100;

    执行时间约 1.6 秒,使用的是 like 方式。

    改成使用全文索引方式:

    test_10
    -- 测试10
    select 
        i.billid
        ,if(0,0,i.qty) as qty         
        ,if(0,0,i.goodstotal) as total   
        ,if(0,0,i.chktotal) as selfchktotal  
        ,if(0,0,i.distotal) as distotal 
        ,if(0,0,i.otherpay) as feetotal  
        ,if(0,0,ifnull(d.costtotal,0)) as costtotal 
        ,if(0,0,ifnull(d.maoli,0)) as maoli  
        ,i.billno
        ,from_unixtime(i.billdate,&#39;%Y-%m-%d&#39;) as billdate /*单据日期*/
        ,from_unixtime(i.createdate,&#39;%Y-%m-%d %H:%i:%s&#39;) as createdate /*制单日期*/
        ,if(i.sdate=0,&#39;&#39;,from_unixtime(i.sdate,&#39;%Y-%m-%d  %H:%i:%s&#39;)) as sdate /*过账日期*/
        ,from_unixtime(i.udate,&#39;%Y-%m-%d %H:%i:%s&#39;) as udate /*最后修改时间*/
        ,i.custid ,c.custname
        ,i.storeid ,k.storename
        ,i.empid ,e.empname
        ,i.userid ,u.username
        ,i.remarks                               /*单据备注*/
        ,i.effect,i.settle,i.redold,i.rednew     /*单据状态*/
        ,i.printtimes /* 打印次数 */
        ,(case  when i.rednew=1 then 1  when i.redold=1 then 2  when i.settle=1 then 3  when i.effect=1 then 4  else 9 end) as state /*单据状态*/
        ,(case  when i.rednew=1 then &#39;红冲单&#39;  when i.redold=1 then &#39;已红冲&#39;  when i.settle=1 then &#39;已结算&#39;  when i.effect=1 then &#39;已过账&#39;  else &#39;草稿&#39; end) as statetext
        ,&#39;&#39; as susername /* 操作人 */
        ,&#39;&#39; as accname /* 科目 */
    from salebill i
    left join coursecentersale d on d.tid=i.tid and d.billid=i.billid
    left join customer c on c.tid=i.tid and c.custid=i.custid
    left join store k on k.tid=i.tid and k.storeid=i.storeid
    left join employee e on e.tid=i.tid and e.empid=i.empid
    left join user u on u.tid=i.tid and u.userid=i.userid
    where i.tid=260434 and (i.billtype = 5 or i.effect = 1)
        and (&#39;_billdate_f_&#39;!=&#39;&#39;)
        and (&#39;_billdate_t_&#39;!=&#39;&#39;)
        and (&#39;_sdate_f_&#39;!=&#39;&#39;)
        and (&#39;_sdate_t_&#39;!=&#39;&#39;)
        and (&#39;_udate_f_&#39;!=&#39;&#39;)
        and (&#39;_udate_t_&#39;!=&#39;&#39;)
        and (&#39;_cdate_f_&#39;!=&#39;&#39;)
        and (&#39;_cdate_t_&#39;!=&#39;&#39;)
        and (&#39;_billid_&#39;!=&#39;&#39;)      /*单据id*/
        and (&#39;_custid_&#39;!=&#39;&#39;)      /*客户ID*/
        and (&#39;_storeid_&#39;!=&#39;&#39;)     /*店仓ID*/
        and (&#39;_empid_&#39;!=&#39;&#39;)       /*业务员ID*/
        and (&#39;_custstop_&#39;!=&#39;&#39;)       /*客户是否停用*/
        and (
            (match(i.billno) against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode))
            or (match(i.remarks) against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode))
            or exists(select 1 from salebilldetail d where d.tid=260434 and d.billid=i.billid and ((match(d.remarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)) or (match(d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;)  in boolean mode))))
            or exists(select 1 from customer c where c.tid=260434 and c.custid=i.custid and (match(c.custname) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)))
            or exists(select 1 from goods g join salebilldetail d on d.tid=g.tid and d.goodsid=g.goodsid where d.tid=260434 and d.billid=i.billid 
         and ((match(g.goodsname) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode))
         or (match(g.goodscode) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode))))
        )
        and i.rednew=0 /*单据列表不含红冲单*/ 
        and i.billid not in (select billid from coursecenter_del t where t.tid=260434)
        and ((i.settle=1 and i.effect=1 and i.redold=0 and i.rednew=0)) /*已结算*/
    order by udate desc,billno desc
    limit 0,100;

    执行时间约 1.6 秒,与使用的是 like 方式差不多。

    最魔幻的地方来了,如果将上面的SQL语句中(salebilldetail表使用全文索引 remarks_fulltextgoodsremarks_fulltext的地方)

    exists(select 1 from salebilldetail d where d.tid=260434 and d.billid=i.billid and ((match(d.remarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)) or (match(d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;)  in boolean mode))))
    test_11

    改成使用全文索引 remarks_goodsremarks_fulltext

    -- 测试11
    exists(select 1 from salebilldetail d where d.tid=260434 and d.billid=i.billid and ((match(d.remarks,d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode))))

    执行时间无限长(跑了半天没成功)?
    经分析,在 where 子句中,一个条件子句中包含一个以上 match 时会出现这样的情况。即:

    -- and 中只有一个全文检索时正常, 用时0.2秒
    select xxx from xxx
    ...
    and (
    	exists(select 1 from salebilldetail d where d.tid=260434 and d.billid=i.billid and ((match(d.remarks,d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode))))
    )
    ...
    
    -- 下面这样就异常了,会慢成百上千倍,用时 160 秒, 如果有更多的 match ,会更夸张的慢下去
    select xxx from xxx
    ...
    and (
    	exists(select 1 from salebilldetail d where d.tid=260434 and d.billid=i.billid and ((match(d.remarks,d.goodsremarks) Against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode))))
    	or match(i.billno) against(concat(&#39;"&#39;,&#39;葡萄&#39;,&#39;"&#39;) in boolean mode)
    )
    ...

    测试结果汇总

    查询 用时(秒) 备注
    test 1 0.765 原始like查询
    test 2 0.834 全文索引 remarks_fulltextgoodsremarks_fulltext
    test 3 0.242 全文索引 remarks_goodsremarks_fulltext
    ---

    test 4 22.654 原始like查询,不过滤 tid
    test 5 24.855 全文索引 remarks_fulltextgoodsremarks_fulltext,  不过滤 tid
    test 6 0.213 全文索引 remarks_goodsremarks_fulltext, 不过滤 tid
    ---

    test 7 0.22 全文索引 remarks_goodsremarks_fulltext, count
    test 8 0.007 全文索引 remarks_goodsremarks_fulltext, 不过滤 tid, count
    ---

    test 9 1.6 业务测试SQL,原始like查询
    test 10 1.6 业务测试SQL,全文索引 remarks_fulltextgoodsremarks_fulltext
    test 11 失败 业务测试SQL,全文索引 remarks_goodsremarks_fulltext

    五、MySQL 版本升级

    因线上系统目前是 RDS MySQL 5.6,故简单描述升级相关问题。

    • Group By: 在 MySQL 5.7 之后,默认使用增加了限制,一些在 MySQL 5.6 可执行的Group By语句,在 5.7 之后会报错,可以更改新版本 MySQL 的 sqlModel

      -- 查询 sql_mode
      select @@SESSION.sql_mode;
      -- 设置
      SET GLOBAL sql_mode = &#39;STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION&#39;;
      -- 或 设置 (修改于当前会 话,关闭当前会话后失效)
      SET SESSION sql_mode = &#39;STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION&#39;;
      -- 刷新
      flush PRIVILEGES;
      
      • ONLY_FULL_GROUP_BY: 对于GROUP BY聚合操作,如果在SELECT中的列,没有在GROUP BY中出现,那么这个SQL是不合法的,因为列不在GROUP BY从句中

      • NO_AUTO_VALUE_ON_ZERO: 该值影响自增长列的插入。默认设置下,插入0NULL代表生成下一个自增长值。如果用户希望插入的值为0,而该列又是自增长的,那么这个选项就有用了。

      • STRICT_TRANS_TABLES:在该模式下,如果一个值不能插入到一个事务中,则中断当前的操作,对非事务表不做限制

      • NO_ZERO_IN_DATE:在严格模式下,不允许日期和月份为零

      • NO_ZERO_DATE:设置该值,mysql数据库不允许插入零日期,插入零日期会抛出错误而不是警告

      • ERROR_FOR_DIVISION_BY_ZERO:在insertupdate过程中,如果数据被零除,则产生错误而非警告。如果未给出该模式,那么数据被零除时MySql返回NULL

      • NO_AUTO_CREATE_USER: 禁止GRANT创建密码为空的用户

      • NO_ENGINE_SUBSTITUTION:如果需要的存储引擎被禁用或未编译,那么抛出错误。不设置此值时,用默认的存储引擎替代,并抛出一个异常

      • PIPES_AS_CONCAT:将"||"视为字符串的连接操作符而非或运算符,这和Oracle数据库是一样是,也和字符串的拼接函数Concat想类似

      • ANSI_QUOTES:启用后,不能用双引号来引用字符串,因为它被解释为识别符

      • 方式2:在配置文件中添加 sql_mode = '对应需要的模式'

      • sql_mode 模式说明:

      • 方式1:重启 MySQL 后失效

    • MySQL8.0 修改了账号密码加密策略 (默认的认证插件由mysql_native_password更改为caching_sha2_password),导致一些可视化软件无法连接 mysql8.0 版本的数据库。如果需要,可以修改默认的策略或者账号密码的认证策略

      [mysqld]
      default_authentication_plugin = mysql_native_password
      

      -- 修改加密规则 
      ALTER USER &#39;root&#39;@&#39;localhost&#39; IDENTIFIED BY &#39;password&#39; PASSWORD EXPIRE NEVER; 
      -- 更新用户密码
      ALTER USER &#39;账号&#39;@&#39;%&#39; IDENTIFIED WITH mysql_native_password BY &#39;密码&#39;;
      -- 刷新权限
      FLUSH PRIVILEGES;
      

      • 方式2:执行语句修改某账号密码验证策略

      • 方式1:配置文件中添加, 让mysql使用原密码策略 (需重启mysql服务)

    • MySQL8.0 授权用户账号语法变更,创建用户的操作已经不支持grant的同时创建用户方式,需要先创建用户再进行授权。

      -- 原来的流程:
      mysql> grant all on *.* to &#39;admin&#39;@&#39;%&#39; identified by &#39;admin&#39;;
      -- 新的正确流程:
      mysql> create user &#39;admin&#39;@&#39;%&#39; identified by &#39;admin&#39;;
      mysql> grant all on *.* to &#39;admin&#39;@&#39;%&#39; ;
      mysql> flush privileges;
      
    • 数据库连接区别

      jdbc:mysql://{ip}:{port}/{db}&#63;characterEncoding=utf8&useSSL=false&serverTimezone=UTC
      // useSSL  如果不配置false 项目可以正常启动但是会提示ssl问题
      // serverTimezone=UTC 必须配置【时区设置成自己对应的时区】否则项目会报错
      

      show variables like &#39;%time_zone%&#39;;
      set global time_zone=&#39;+8:00&#39;;
      

      • 如果时区问题还不能解决:

      • JDBC 连接串修改如下(首先需要驱动使用8.0对应连接的驱动):

    • MySQL 5.7 原生支持JSON类型,并引入了众多JSON函数

    • MySQL 8.0 JSON字段的部分更新(JSON Partial Updates)

    • MySQL 8.0 默认字符集由latin1修改为utf8mb4

    • MySQL 8.0 正则表达式的增强,新增了4个相关函数,REGEXP_INSTR()REGEXP_LIKE()REGEXP_REPLACE()REGEXP_SUBSTR()

    • MySQL 8.0 GROUP BY语句不再隐式排序 (忽略在Group By中的排序命令,如 desc, asc)

    以上是mysql ft指的是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

    陳述:
    本文轉載於:yisu.com。如有侵權,請聯絡admin@php.cn刪除