最近在学习MySQL全文索引的知识,基本搞清了功能以及使用方式,整理了相关资料分享出来一起学习进步哈

目录

1. 倒排索引

2. InnoDB全文检索

3. MySQL全文检索

3.1 Natural Language (自然语言模式)

3.2 Boolean(布尔模式)

3.3 Query Expansion(查询扩展)

4. ngram 分词器

5. 参考资料


全文检索(Full-Text Search)是将存储于数据库中的整本书或整篇文章中的任意内容信息查找出来的技术。它可以根据需要获得全文中有关章、节、段、句、词等信息,也可以进行各种统计和分析。

1. 倒排索引

在老版本的MySQL数据库中,InnoDB存储引擎并不支持全文检索技术,从InnoDB 1.2.x版本开始,InnoDB存储引擎开始支持全文检索,其支持MyISAM存储引擎的全部功能,并且还支持其他的一些特性,在介绍其使用之前,先介绍下倒排索引(invertd index)。

全文检索通常使用倒排索引(invertd index)来实现。倒排索引同B+树索引一样,也是一种索引结构。它在辅助表(auxiliary table)中存储了单词与单词自身在一个或多个文档中所在位置之间的映。这通常利用关联数组实现,其拥有两种表现形式:

inverted file index, 其表现形式为 {单词,单词所在文档的ID}

full inverted index, 其表现形式为 {单词,(单词所在文档的ID,在具体文档中的位置)},如下图这个例子,表格中存储表t的内容

全文检索表 t
DocumentId Text DocumentId Text
1 Pease porridge hot, pease porridge cold 4 Some like it hot, some like it cold
2 Pease porridge in the pot 5 Some like it in the pot
3 Nine days old 6 Nine days old

DocumentId 表示进行全文检索文档的IdText表示存储的内容,用户需要对存储的这些文档内容进行全文检索。例如,查找出现过Some 单词的文档Id, 又或者查找单个文档中出现过两个Some单词的文档Id,等等。

对于 inverted file index 的关联数组,其存储的内容如下所示。

inverted file index 的关联数组
Number Text Documents Number Text Documents
1 cold 1,4 8 old 3,6
2 days 3,6 9 pease 1,2
3 hot 1,4 10 porridge 1,2
4 in 2,5 11 pot 2,5
5 it 4,5 12 some 4,5
6 like 4,5 13 the 2,5
7 nine 3,6      

可以看到单词cold存在于文档1和4中,单词 days 存在于文档 3 和 6 中。之后再要进行全文查询就简单了。可以直接根据 Documents 得到包含查询关键字的文档。对于 inverted file index,其仅存取文档 Id,而 full inverted index 存储的是一对 (pair),即(DocumentId, Position), 因此其存储的倒排索引如下表所示:

full inverted index 的关联数组
Number Text Documents Number Text Documents
1 cold (1:6),(4:8) 8 old (3:3),(6:3)
2 days (3:2),(6:2) 9 pease (1:1,4),(2:1)
3 hot (1:3),(4:4) 10 porridge (1:2,5),(2:2)
4 in (2:3),(5:4) 11 pot (2:5),(5:6)
5 it (4:3, 7),(5:3) 12 some (4:1,5),(5:1)
6 like (4:2,6),(5:2) 13 the (2:4),(5:5)
7 nine (3:!),(6:1)      

full inverted index 还存储了单词所在的位置信息,如 code 这个单词出现在 (1:6),即文档 1 的第 6 个单词为code。相比之下, full  inverted index 占用更多的空间,但是能更好地定位数据,并扩充一些其他的搜索特性。

2. InnoDB全文检索

InnoDB存储引擎从 1.2.x 版本开始支持全文检索的技术,其采用 full inverted index 的方式。在 InnoDB存储引擎中,将 (DocumentId, Position)视为一个 "ilist"。因此在全文检索的表中,有两个列,一个是word字段,另一个是 ilist字段, 并且在word字段上设有索引。此外,由于 InnoDB 存储引擎在 ilist 字段中存放了 Position 信息,故可以进行 Proximity Search(邻近检索),而MyISAM 存储引擎不支持该特性,下文给出邻近检索的例子。

正如之前所说的那样,倒排索引需要将 word 字段存放到一张表中,这个表称为 Auxiliary Table ( 辅助表 )。在 InnoDB 存储引擎中,为了提高全文检索的并行性能,共有 6 张 Auxiliary Table,目前每张表根据 word 的 Latin 编码进行分区。

Auxiliary Table 是持久的表,存放于磁盘上。然而在 InnoDB 存储引擎的全文索引中,还有另外一个重要的概念 FTS Index Cache( 全文检索索引缓存表 ),其用来提高全文检索的性能。

FTS Index Cache 是一个红黑树结构,其根据( word, ilist) 进行排序。这意味着插入的数据已经更新了对应的表,但是对全文索引的更新可能在分词操作后还在 FTS Index Cache 中,Auxiliary Table 可能还没有更新。InnoDB 存储引擎会批量对 Auxiliary Table  进行更新,而不是每次插入后更新一次Auxiliary Table 。当对全文检索进行查询时,Auxiliary Table  首先会将在FTS Index Cache  中对应的word 字段合并到 Auxiliary Table 中,然后再进行查询。这种merge 操作类似于 Insert Buffer 功能,不同的是 Insert Buffer 是一个持久的对象,并且其是一个B+ 树的结构。然而 FTS Index Cache 的作用又和 Insert Buffer  类似,它提高了InnoDB 存储引擎的性能,并且由于其根据红黑树排序后进行批量插入,其产生的 Auxiliary Table 相对较小。

Innodb 存储引擎允许用户查看指定倒排索引的Auxiliary Table中分词的信息,可以通过设置参数 innodb_ft_aux_table 来观察倒排索引的 Auxiliary Table。下面的SQL语句设置查看 test 数据库中 fts_a 表的Auxiliary Table:

SET GLOBAL innodb_ft_aux_table="test/fts_a";

在上述设置完成后,就可以通过查询 information_schema 库中的表 INNODB_FT_INDEX_TABLE 得到表 fts_a 中的分词信息。

对于InnoDB 存储引擎而言,其总是在事务提交时将分词写入到 FTS Index Cache,然后再通过批量更新写入到磁盘。虽然 InnoDB 存储引擎通过一种延时的、批量的写入方式来提高数据库的性能,但是上述操作仅在事务提交时发生。

当数据库关闭时,在 FTS Index Cache 中的数据库会同步到磁盘上的  Auxiliary Table 中。然而,如果当数据库发生宕机时,一些 FTS Index Cache 中的数据库可能未被同步到磁盘上。那么下次重启数据库时,当用户对表进行全文检索( 查询或者插入操作)时,InnoDB 存储引擎会自动读取未完成的文档,然后进行分词操作,再将分词的结果放入到 FTS Index Cache 中。

参数 innodb_ft_cache_size 用来控制 FTS Index Cache 的大小,默认值为32M。当该缓存满时,会将其中的(word,ilist)分词信息同步到磁盘的 Auxiliary Table中。增大该参数可以提高全文检索的性能,但是在宕机时,未同步到磁盘中的索引信息可能需要更长的时间进行恢复。

FTS Document ID 是另外一个重要的概念。在 InnoDB 存储引擎中,为了支持全文检索,必须有一个列与 word进行映射,在InnoDB 中这个列被命名为 FTS_DOC_ID,其类型必须是 BIGINT UNSIGNED NOT NULL,并且 InnoDB 存储引擎自动会在该列上加入一个名为 FTS_DOC_ID_INDEX 的 Unique Index。上述这些操作都由 InnoDB 存储引擎自己完成,用户也可以在建表时自动添加FTS_DOC_ID,以及相应的Unique Index。由于列名为FTS_DOC_ID 的列具有特殊意义,因此创建时必须注意相应的类型,否则MySQL 数据库会抛出错误,如下图

文档中分词的插入操作是在事务提交时完成,然而对于删除操作,其在事务提交时,不删除磁盘  Auxiliary Table 中的记录,而只是删除  FTS Index Cache 中的记录,并将其保存在 DELETED auxiliary table 中。在设置参数 innodb_ft_aux_table 后,用户同样可以访问 information_schema 库下的表 INNODB_FT_DELETED 来观察删除的 FTS Document ID。

由于文档的DML 操作实际并不删除索引中的数据,相反还会在对应的DELETED 表中插入记录,因此随着应用程序的允许,索引会变得非常大,即使索引中的有些数据已经被删除,查询也不会选择这类记录。为此,InnoDB 存储引擎提供了一种方式,允许用户手动地将已经存储的记录从索引中彻底删除,该命令是 optimize table。因为 optimize table 还会进行一些其他的操作,如 Cardinality 的重新统计,若用户希望仅对倒排索引进行操作,那么可以通过参数 innodb_optimize_fulltext_only进行设置,如:

set global innodb_optimize_fulltext_only=1;optimize table fts_a;

若被删除的文档非常多,那么 optimize table 操作可能需要占用非常多的时间,这会影响影响应用程序的并发性,并极大地降低用户的响应时间。用户可以参数 innodb_ft_num_word_optimize 来限制每次实际删除的分词数量。该参数的默认值为2000。

下面通过例子来观察,首先通过如下代码创建表 fts_a:

create table fts_a (FTS_DOC_ID bigint unsigned auto_increment not null,body text,primary key(FTS_DOC_ID));insert into fts_a select null, 'Pease porridge in the pot';
insert into fts_a select null, 'Pease porridge hot, pease porridge cold';
insert into fts_a select null, 'Nine days old';
insert into fts_a select null, 'Some like it hot, some like it cold';
insert into fts_a select null, 'Some like it in the pot';
insert into fts_a select null, 'Nine days old';
insert into fts_a select null, 'I like code days';
create fulltext index idx_fts on fts_a(body);

上述代码创建了表 fts_a,由于body字段是进行全文检索的字段,因此创建一个类型为 FULLTEXT的索引。这里首先导入数据,然后再进行倒排索引的创建,这也是比较推荐的一张方式,创建完成后观察表中的数据:

通过设置 innodb_ft_aux_table 来查看分词对应的信息:

SET GLOBAL innodb_ft_aux_table="study/fts_a";select * from information_schema.INNODB_FT_INDEX_TABLE;

可以看到每个word都对应了一个DOC_ID 和 POSITION。此外,还记录了FIRST_DOC_ID、LAST_DOC_ID以及 DOC_COUNT,分别代表了该 word 第一次出现的文档ID,最后一次出现的文档ID,以及该word在多少个文档中存在。若执行如下语句,会删除FTS_DOC_ID 为7 的文档:

delete from fts_a where FTS_DOC_ID=7;

由于之前的介绍,InnoDB 存储引擎并不会直接删除索引中对应的记录,而是将删除的文档ID插入到DELETED表,因此可以进行如下的查询:

select * from information_schema.INNODB_FT_DELETED;

可以看到删除的文档ID插入到了表 INNODB_FT_DELETED中,若用户想要彻底删除倒排索引中该文档的分词信息,那么可以运行如下的SQL语句:

set global innodb_optimize_fulltext_only=1;
optimize table fts_a;
select * from information_schema.INNODB_FT_BEING_DELETED;

通过上面的例子可看到,运行命令 optimize table 可将记录进行彻底的删除,并且彻底删除的文档ID会记录到表 INNODB_FT_BEING_DELETE中,此外,由于7这个文档ID已经被删除,因此不允许再次插入这个文档ID,否则数据库会抛出错误。

接下来介绍下 stopword 列表( 停用词 ),其表示该列表中的word 不需要对其进行索引分词操作。例如,对于the 这个单词,由于其不具有具体的意义,因此将其视为 stopword。InnoDB 存储引擎有一张默认的 stopword 列表,其在 information_schema下,表名为 INNODB_FT_DEFAULT_STOPWORD,默认有36个stopword。此外用户也可以通过参数 innodb_ft_server_stopword_table 来自定义stopword 列表,如下:

// 查看默认停用词表
SELECT * FROM INFORMATION_SCHEMA.INNODB_FT_DEFAULT_STOPWORD;// 自定义停用词表
create table user_stopword(value VARCHAR(30)) ENGINE= INNODB;set global innodb_ft_server_stopword_table = "test/user_stopword";

使用Innodb 存储引擎的全文检索还存在以下的限制:

  1. 每张表只能有一个全文检索的索引
  2. 由多列组合而成的全文检索的索引列必须使用相同的字符集与排序规则。
  3. 不支持没有单词界定符(delimiter)的语言,如中文、日语、韩语等(这一点可以通过自定义分词器ngram来解决,下文有介绍)。

3. MySQL全文检索

介绍完了InnoDB 的全文检索,接下来看下MySQL的全文检索。

MySQL数据库支持全文检索(Full-Text Search)的查询,其语法为:

MATCH (col1, col2,...) AGAINST (expr [search_modifier])search_modifier:
{IN NATURAL LANGUAGE MODE| IN NATURAL LANGUAGE MODE WITH QUERY EXPANSION| IN BOOLEAN MODE| WITH QUERY EXPANSION
}

MySQL 数据库通过 MATCH()···AGAINST()语法支持全文检索的查询,MATCH 指定了需要被查询的列,AGAINST指定了使用何种方法去进行查询。下面将对各种查询模式进行详细的介绍。

3.1 Natural Language (自然语言模式)

全文检索通过MATCH函数进行查询,默认采用 Natural Language 模式,其表示查询带有指定word的文档,对于上文创建的表fts_a,查询body字段中带有Pease 的文档,若不使用全文索引技术,则允许使用如下语句:

select * from fts_a where like '%Pease%'

显然该语句不能使用B+树索引,若采用全文检索技术,可以使用下面的SQL语句进行查询:

select * from fts_a where match(body) against ('porridge' in natural language mode);

由于NATURAL LANGUAGE MODE 是默认的全文检索查询模式,因此可以省略查询修饰符,即上述语句可以写为:

select * from fts_a where match(body) against ('porridge');

在where条件中使用MATCH函数,查询返回的结果是根据相关性(Relevance)进行降序排序的,即相关性最高的结果放在第一位。相关性的值是一个非负的浮点数字,0表示没有任何相关性。根据MySQL官方文档可知,其相关性的计算依据以下四个条件:

  1. word是否在文档中出现。
  2. word在文档中出现的次数。
  3. word在索引列中的数量。
  4. 多少个文档中包含该word。

对于上述查询,由于 Porridge 在文档2中出现了2次,因而具有更高的相关性,故第一个显示。MySQL相关性的计算公式可以查询官方文档得到,这里不再详述。

用户可以通过如下SQL语句查看相关性:

 select fts_doc_id, body, match(body) against ('Porridge' in natural language mode) as Relevance from fts_a;

对于InnoDB 存储引擎的全文检索,还需要考虑一下的因素:

  1. 查询的word 在 stopword 列中,忽略该字符串的查询。
  2. 查询的word 的字符长度是否在区间 [innodb_ft_min_token_size, innodb_ft_max_token_size] 中。

如果词在stopword 中,则不对该词进行查询。参数 innodb_ft_min_token_size和 innodb_ft_max_token_size 控制InnoDB 存储引擎查询字符的长度,当长度小于innodb_ft_min_token_size 或者 大于innodb_ft_max_token_size 时,会忽略该词的搜索。在InnoDB 存储引擎中,参数 innodb_ft_min_token_size 默认值为3,参数 innodb_ft_max_token_size 默认值为84。

3.2 Boolean(布尔模式)

MySQL数据库允许使用 IN BOOLEAN MODE 修饰符来进行全文检索。当使用该修饰符时,查询字符串的前后字符会有特殊的含义,例如下面的语句要求查询有字符串 Pease 但没有 hot 的文档,其中 + 和 - 分别表示这个单词必须出现,或者一定不存在。

select * from fts_a where match(body) against ('+Pease -hot' in boolean mode)\G;

Boolean 全文检索支持一下几种操作符:

操作符 含义
+ 表示该word必须存在
- 表示该word必须被排除
(空) 表示该word是可选的,但是如果出现,其相关性会更高
@distance 表示查询的多个单词之间的距离是否在distance之内,distance的单位是词。这种全文检索的查询也称为Proximity Search。如MATCH (body) AGAINST (' "Peace pot"@30 in boolean mode) 表示字符串Peace 和 pot 之间的距离需在30个词以内。
> 表示出现该单词时增加相关性
< 表示出现该单词时降低相关性
~ 表示允许出现该单词,但是出现时相关性为负(全文检索查询允许负相关性)
* 表示以该单词开头的单词,如lik*,表示可以是lik、like,又或者是likes。
" 表示短语

下面展示每个操作符对应的例子:

1. 查找既有 pease 又有 hot 的文档:

select * from fts_a where match(body) against ('+pease +hot' in boolean mode);

2. 查找只有pease 但没有 hot 的文档

 select * from fts_a where match(body) against ('+pease -hot' in boolean mode);

3. 查找有pease 或 hot 的文档

select * from fts_a where match(body) against ('pease hot' in boolean mode);

 4. Proximity Search 临近查找

select * from fts_a where match(body) against (' "hot cole"@4' in boolean mode);
select * from fts_a where match(body) against (' "hot cole"@3' in boolean mode);

hot 和 cole 之间距离有{, pease porridge cole} 四个词,因此后一语句不满足条件。

5. > 增加相关性

select fts_doc_id, body, MATCH(body) AGAINST ('like >pot' in boolean mode) AS Relevance from fts_a;

上述SQL语句查询根据是否有单词like 或 pot 进行相关性统计,并且出现单词pot后相关性需要增加。文档4虽然有两个like单词,但是没有pot,因此相关性没有1和5高。

6. < 降低相关性

下面的查询增加了 '<some' 的条件得到的结果:

select fts_doc_id, body, MATCH(body) AGAINST ('like >hot <some' in boolean mode) AS Relevance from fts_a;

可以发现文档5的相关性变为了负,这是因为虽然其中存在like单词,但是也存在some单词,所以根据查询条件,其相关性变为了负相关。

7. * 通配符

select * from fts_a where MATCH(body) AGAINST ('po*' in boolean mode);

可以看到最后结果中的文档包含以po开头的单词。

8. 短语查询

 select * from fts_a where MATCH(body) AGAINST('like it hot' in boolean mode);

select * from fts_a where MATCH(body) AGAINST('"like it hot"' in boolean mode);

可以看到第一条SQL语句没有使用 ""将 like it hot 视为一个短语,而只是将其视为3个单词,因此返回4个结果,而第二条SQL语句使用"likt it hot",因此查询的是短语,故仅文档4符合查询条件。

3.3 Query Expansion(查询扩展)

MySQL数据库还支持全文检索的扩展查询。这种查询通常在查询的关键词太短,用户需要implied knowledge(隐含知识)时进行。例如,对于单词database的查询,用户可能希望查询的不仅仅是包含database的文档,可能还指那些包含MySQL、oracle、DB2单词。而这时可以使用Query Expansion模式开启全文检索的implied knowledge。

通过在查询短语中添加 WITH QUERY EXPANSIONIN NATURAL LANGUAGE MODE WITH QUERY EXPANSION 可以开启blind query expansion(又称为automatic relevance feedback)。该查询分为两个阶段:

  1. 第一阶段:根据搜索的单词进行全文索引查询。
  2. 第二阶段:根据第一阶段产生的结果分词后再进行一次全文检索查询。

下面结合一个例子来说明,首先建立测试表:

 create table articles(id int unsigned auto_increment not null primary key,title VARCHAR(200),body text,fulltext(title, body))engine=InnoDB;insert into articles (title, body) values('MySQL Tutorial', 'DBMS stands for DataBase ...'),('How To Use MySQL Well', 'After you went through a ...'),('Optimizing MySQL', 'In this turitual we will show ...'),('1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),('MySQL vs. YourSQL','In the following database comparision ...'),('MySQL Security','When configured properly, MySQL ...'),('Tuning DB2','For IBM database ...'),('IBM History','DB2 history for IBM ...');

在这个例子中,并没有显示创建FTS_DOC_ID列,因此InnoDB存储引擎会自动建立该列,并添加唯一索引。此外,表articles 的全文检索索引是根据列title 和 body 的联合索引。接着根据database 关键字进行的全文索引查询:

 select * from articles where match(title, body) against ('database');

可以看到,查询返回了3条记录,body字段包含database关键字。接着开启Query Expansion,观察结果:

select * from articles where match(title, body) against ('database' with query expansion);

可以看到最后得到8条结果,除了之前包含的 database的记录,也有包含title 或 body 字段中包含MySQL、DB2的文档,这就是Query Expansion。

由于Query Expansion 的全文检索可能带来许多非相关性的查询,因此在使用时,用户可能需要非常谨慎。

4. ngram 分词器

前面我们说过,InnoDB存储引擎内置的分词器不支持中文、日文等语言,因为这些语言并不使用空格作为分词符,为了解决这个问题,MySQL提供了ngram全文解析器。自MySQL5.7.6版起,MySQL将ngram全文解析器作为内置的服务器插件,这意味着当MySQL数据库服务器启动时,MySQL会自动加载该插件。 MySQL支持用于InnoDBMyISAM存储引擎的ngram全文解析器。

根据定义,ngram是来自文本序列的多个字符的连续序列。 ngram全文解析器的主要功能是将文本序列标记为n个字符的连续序列。

以下说明了ngram全文解析器如何标记不同值n的文本序列:

n = 1: '全','文','检','索'
n = 2: '全文', '文检', '检索'
n = 3: '全文检', '文检索'
n = 4: '全文检索'

要创建使用ngram全文解析器的FULLTEXT索引,可以在CREATE TABLE,ALTER TABLE或CREATE INDEX语句中添加WITH PARSER ngram

CREATE TABLE ft_chn (id INT PRIMARY KEY AUTO_INCREMENT,title VARCHAR(255),body TEXT,FULLTEXT ( title , body ) WITH PARSER NGRAM
)  ENGINE=INNODB CHARACTER SET UTF8;

值得注意的是,ngram的自然语言搜索模式中,搜索项被转换为ngram值的并集。在ngram布尔模式中,搜索项被转换成ngram短语搜索。

默认情况下,ngram中的令牌大小(n)为2,要更改令牌大小,请使用ngram_token_size配置选项,这是个只读选项,有两种配置方式,值的范围是:110,一种是启动时传参,另一种是写到配置文件里:

// 启动时传参
mysqld --ngram_token_size=1// 写到配置文件里
[mysqld]
ngram_token_size=1

MySQL全文索引的基本知识就总结到这里。

5. 参考资料

1. 《MySQL技术内幕 InnoDB存储引擎第二版》姜承尧著

2.  MySQL ngram全文解析器

3. 关于倒排索引讨论

4. 倒排索引

5. MySQL · 引擎特性 · InnoDB 全文索引简介

================================================================================================

Linux应用程序、内核、驱动、后台开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。...

InnoDB MySQL 全文索引 学习笔记相关推荐

  1. MySQL 索引学习笔记

    MySQL 索引学习笔记 索引基本概念 索引优点 B-Tree 索引 基本原理 使用场景 使用限制 哈希索引 基本原理 使用限制 自适应哈希索引 处理哈希冲突 相关面试题 高性能索引策略 独立的列 前 ...

  2. MySQL语法学习笔记

    MySQL语法学习笔记 学习之道,非尽心竭力者不能进也!我是小七黛,欢迎查看我的笔记,有问题欢迎交流探讨. SQL是一种结构查询语言,用于查询关系数据库的标准语言,包括若干关键字和一致的语法,便于数据 ...

  3. Mysql 高级学习笔记

    Mysql 高级学习笔记 文章目录 Mysql 高级学习笔记 一.Mysql 基础 1. 聚合函数 2. having 3. sql 的执行顺序 4. 约束 5. 试图 二.Mysql 高级 1. M ...

  4. 最新、最全、最详细的 MySQL 数据库学习笔记总结(2021最新版)

    数据库是什么 数据库管理系统,简称为DBMS(Database Management System),是用来存储数据的管理系统. DBMS 的重要性 无法多人共享数据 无法提供操作大量数据所需的格式 ...

  5. MySQL高级学习笔记(四)

    文章目录 MySQL高级学习笔记(四) 1. MySql中常用工具 1.1 mysql 1.1.1 连接选项 1.1.2 执行选项 1.2 mysqladmin 1.3 mysqlbinlog 1.4 ...

  6. linux数据库创建score表,MySQL数据库学习笔记

    MySQL数据库学习笔记phpma (实验环境:Redhat9.0,MySQL3.23.54) 纲要: 一,连接MySQL phpma 二,MySQL管理与授权 三,数据库简单操作 四, 数据库备份 ...

  7. MySQL数据库学习笔记(十二)----开源工具DbUtils的使用(数据库的增删改查)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  8. MySQL数据库学习笔记(九)----JDBC的ResultSet接口(查询操作)、PreparedStatement接口重构增删改查(含SQL注入的解释)...

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  9. MySQL 8——学习笔记03(插入、更新、删除 数据 [DML语句]、查询数据 [DQL语句])

    MySQL 8--学习笔记03(插入.更新.删除 数据 [DML语句]) 一.插入数据 1.1 插入所有字段.插入部分字段 1.2 同时插入多条记录(批量插入) 1.3 将查询结果插入到表中 二.更新 ...

最新文章

  1. 【 FPGA 】控制数码管动态扫描显示的小实验
  2. lr:lr中错误解决方法19种
  3. Android-可自动缩小字体的TextView
  4. WKWebView-填坑总结
  5. 运算符的优先级表(从高到低)
  6. UVA12321 Gas Stations【贪心】
  7. nyoj------20吝啬的国度
  8. AD ---- 活动目录的日常管理操作(3)
  9. CentOS 6.5安装配置Nginx
  10. Excel VBA内部函数大全
  11. qrcodejs2的错误、公众号识别不了二维码、公众号识别二维码没反应
  12. udacity深度学习--2. 深度学习简介--LESSON5 Jupyter notebook
  13. java 是什么_java中是什么意思?
  14. 按键精灵 打开windows系统应用
  15. jQuery 实现贪吃蛇游戏
  16. 暗黑2魔电西格玛攻略_魔电西格玛,暗黑2最佳继承者-1949游戏测评
  17. DDD为什么能火起来?和微服务有啥关系?
  18. 声网Q4亏损扩大1.6倍,持股4.9%的联合创始人陶思明离职
  19. RPG游戏制作-04-接入脚本前的准备
  20. 【小技巧】一些matlab中常用的快捷键使用总结

热门文章

  1. 当向后台插入或读取JSON数据遇见回车时
  2. Java 反射 不定参数bug
  3. 批处理相对路径51CTO自动领豆(Python)
  4. pointnet分割自己的点云数据_点云学习历史文章大汇总
  5. shiro权限管理_重量级课程发布~企业权限管理平台(SpringBoot2.0+Shiro+Vue)
  6. 权重可以当做概率幅吗?---用神经网络的收敛模拟机械波的波动
  7. ps怎么把一个颜色替换成另一个颜色_常用的60个PS技巧,助你成为PS大神!
  8. 【数理知识】《矩阵论》方保镕老师-第1章-矩阵的几何理论
  9. 2.10 局部最优的问题-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  10. 梯度下降法Gradient Descent深度学习 机器学习