MySQL 实际执行 SQL 顺序
-
mysql 执行的顺序:随着 Mysql 版本的更新换代, 其优化器也在不断的升级, 优化器会分析不同执行顺序产生的性能消耗不同而动态调整执行顺序。
-
下面是经常出现的查询顺序:
总结:mysql 从 FROM 开始执行~
2.2、JOIN 连接查询
常见的 JOIN 查询图
建表 SQL
CREATE TABLE tbl_dept(
id INT(11) NOT NULL AUTO_INCREMENT,
deptName VARCHAR(30) DEFAULT NULL,
locAdd VARCHAR(40) DEFAULT NULL,
PRIMARY KEY(id)
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
CREATE TABLE tbl_emp (
id INT(11) NOT NULL AUTO_INCREMENT,
NAME VARCHAR(20) DEFAULT NULL,
deptId INT(11) DEFAULT NULL,
PRIMARY KEY (id),
KEY fk_dept_Id (deptId)
#CONSTRAINT 'fk_dept_Id' foreign key ('deptId') references 'tbl_dept'('Id')
)ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
INSERT INTO tbl_dept(deptName,locAdd) VALUES('RD',11);
INSERT INTO tbl_dept(deptName,locAdd) VALUES('HR',12);
INSERT INTO tbl_dept(deptName,locAdd) VALUES('MK',13);
INSERT INTO tbl_dept(deptName,locAdd) VALUES('MIS',14);
INSERT INTO tbl_dept(deptName,locAdd) VALUES('FD',15);
INSERT INTO tbl_emp(NAME,deptId) VALUES('z3',1);
INSERT INTO tbl_emp(NAME,deptId) VALUES('z4',1);
INSERT INTO tbl_emp(NAME,deptId) VALUES('z5',1);
INSERT INTO tbl_emp(NAME,deptId) VALUES('w5',2);
INSERT INTO tbl_emp(NAME,deptId) VALUES('w6',2);
INSERT INTO tbl_emp(NAME,deptId) VALUES('s7',3);
INSERT INTO tbl_emp(NAME,deptId) VALUES('s8',4);
INSERT INTO tbl_emp(NAME,deptId) VALUES('s9',51);
123456789101112131415161718192021222324252627282930
- tbl_dept 表结构
mysql> select * from tbl_dept;
+----+----------+--------+
| id | deptName | locAdd |
+----+----------+--------+
| 1 | RD | 11 |
| 2 | HR | 12 |
| 3 | MK | 13 |
| 4 | MIS | 14 |
| 5 | FD | 15 |
+----+----------+--------+
5 rows in set (0.00 sec)
1234567891011
- tbl_emp 表结构
mysql> select * from tbl_emp;
+----+------+--------+
| id | NAME | deptId |
+----+------+--------+
| 1 | z3 | 1 |
| 2 | z4 | 1 |
| 3 | z5 | 1 |
| 4 | w5 | 2 |
| 5 | w6 | 2 |
| 6 | s7 | 3 |
| 7 | s8 | 4 |
| 8 | s9 | 51 |
+----+------+--------+
8 rows in set (0.00 sec)
7 种 JOIN 示例
笛卡尔积
-
tbl_emp 表和 tbl_dept 表的笛卡尔乘积:
select * from tbl_emp, tbl_dept; -
其结果集的个数为:5 * 8 = 40
mysql> select * from tbl_emp, tbl_dept;
+----+------+--------+----+----------+--------+
| id | NAME | deptId | id | deptName | locAdd |
+----+------+--------+----+----------+--------+
| 1 | z3 | 1 | 1 | RD | 11 |
| 1 | z3 | 1 | 2 | HR | 12 |
| 1 | z3 | 1 | 3 | MK | 13 |
| 1 | z3 | 1 | 4 | MIS | 14 |
| 1 | z3 | 1 | 5 | FD | 15 |
| 2 | z4 | 1 | 1 | RD | 11 |
| 2 | z4 | 1 | 2 | HR | 12 |
| 2 | z4 | 1 | 3 | MK | 13 |
| 2 | z4 | 1 | 4 | MIS | 14 |
| 2 | z4 | 1 | 5 | FD | 15 |
| 3 | z5 | 1 | 1 | RD | 11 |
| 3 | z5 | 1 | 2 | HR | 12 |
| 3 | z5 | 1 | 3 | MK | 13 |
| 3 | z5 | 1 | 4 | MIS | 14 |
| 3 | z5 | 1 | 5 | FD | 15 |
| 4 | w5 | 2 | 1 | RD | 11 |
| 4 | w5 | 2 | 2 | HR | 12 |
| 4 | w5 | 2 | 3 | MK | 13 |
| 4 | w5 | 2 | 4 | MIS | 14 |
| 4 | w5 | 2 | 5 | FD | 15 |
| 5 | w6 | 2 | 1 | RD | 11 |
| 5 | w6 | 2 | 2 | HR | 12 |
| 5 | w6 | 2 | 3 | MK | 13 |
| 5 | w6 | 2 | 4 | MIS | 14 |
| 5 | w6 | 2 | 5 | FD | 15 |
| 6 | s7 | 3 | 1 | RD | 11 |
| 6 | s7 | 3 | 2 | HR | 12 |
| 6 | s7 | 3 | 3 | MK | 13 |
| 6 | s7 | 3 | 4 | MIS | 14 |
| 6 | s7 | 3 | 5 | FD | 15 |
| 7 | s8 | 4 | 1 | RD | 11 |
| 7 | s8 | 4 | 2 | HR | 12 |
| 7 | s8 | 4 | 3 | MK | 13 |
| 7 | s8 | 4 | 4 | MIS | 14 |
| 7 | s8 | 4 | 5 | FD | 15 |
| 8 | s9 | 51 | 1 | RD | 11 |
| 8 | s9 | 51 | 2 | HR | 12 |
| 8 | s9 | 51 | 3 | MK | 13 |
| 8 | s9 | 51 | 4 | MIS | 14 |
| 8 | s9 | 51 | 5 | FD | 15 |
+----+------+--------+----+----------+--------+
40 rows in set (0.00 sec)
inner join
-
tbl_emp 表和 tbl_dept 的交集部分(公共部分)
-
select * from tbl_emp e inner join tbl_dept d on e.deptId = d.id;
mysql> select * from tbl_emp e inner join tbl_dept d on e.deptId = d.id;
+----+------+--------+----+----------+--------+
| id | NAME | deptId | id | deptName | locAdd |
+----+------+--------+----+----------+--------+
| 1 | z3 | 1 | 1 | RD | 11 |
| 2 | z4 | 1 | 1 | RD | 11 |
| 3 | z5 | 1 | 1 | RD | 11 |
| 4 | w5 | 2 | 2 | HR | 12 |
| 5 | w6 | 2 | 2 | HR | 12 |
| 6 | s7 | 3 | 3 | MK | 13 |
| 7 | s8 | 4 | 4 | MIS | 14 |
+----+------+--------+----+----------+--------+
7 rows in set (0.00 sec)
left join
-
tbl_emp 与 tbl_dept 的公共部分 + tbl_emp 表的独有部分
-
left join:取左表独有部分 + 两表公共部分
-
select * from tbl_emp e left join tbl_dept d on e.deptId = d.id;
mysql> select * from tbl_emp e left join tbl_dept d on e.deptId = d.id;
+----+------+--------+------+----------+--------+
| id | NAME | deptId | id | deptName | locAdd |
+----+------+--------+------+----------+--------+
| 1 | z3 | 1 | 1 | RD | 11 |
| 2 | z4 | 1 | 1 | RD | 11 |
| 3 | z5 | 1 | 1 | RD | 11 |
| 4 | w5 | 2 | 2 | HR | 12 |
| 5 | w6 | 2 | 2 | HR | 12 |
| 6 | s7 | 3 | 3 | MK | 13 |
| 7 | s8 | 4 | 4 | MIS | 14 |
| 8 | s9 | 51 | NULL | NULL | NULL |
+----+------+--------+------+----------+--------+
8 rows in set (0.00 sec)
right join
-
tbl_emp 与 tbl_dept 的公共部分 + tbl_dept表的独有部分
-
right join:取右表独有部分 + 两表公共部分
-
select * from tbl_emp e right join tbl_dept d on e.deptId = d.id;
mysql> select * from tbl_emp e right join tbl_dept d on e.deptId = d.id;
+------+------+--------+----+----------+--------+
| id | NAME | deptId | id | deptName | locAdd |
+------+------+--------+----+----------+--------+
| 1 | z3 | 1 | 1 | RD | 11 |
| 2 | z4 | 1 | 1 | RD | 11 |
| 3 | z5 | 1 | 1 | RD | 11 |
| 4 | w5 | 2 | 2 | HR | 12 |
| 5 | w6 | 2 | 2 | HR | 12 |
| 6 | s7 | 3 | 3 | MK | 13 |
| 7 | s8 | 4 | 4 | MIS | 14 |
| NULL | NULL | NULL | 5 | FD | 15 |
+------+------+--------+----+----------+--------+
8 rows in set (0.00 sec)
left join without common part
-
tbl_emp 表的独有部分:将 left join 结果集中的两表公共部分去掉即可
where d.id is null -
select * from tbl_emp e left join tbl_dept d on e.deptId = d.id where d.id is null;
mysql> select * from tbl_emp e left join tbl_dept d on e.deptId = d.id where d.id is null;
+----+------+--------+------+----------+--------+
| id | NAME | deptId | id | deptName | locAdd |
+----+------+--------+------+----------+--------+
| 8 | s9 | 51 | NULL | NULL | NULL |
+----+------+--------+------+----------+--------+
1 row in set (0.00 sec)
right join without common part
-
tbl_dept表的独有部分:将 right join 结果集中的两表公共部分去掉即可:where e.deptId is null
-
select * from tbl_emp e right join tbl_dept d on e.deptId = d.id where e.deptId is null;
mysql> select * from tbl_emp e right join tbl_dept d on e.deptId = d.id where e.id is null;
+------+------+--------+----+----------+--------+
| id | NAME | deptId | id | deptName | locAdd |
+------+------+--------+----+----------+--------+
| NULL | NULL | NULL | 5 | FD | 15 |
+------+------+--------+----+----------+--------+
1 row in set (0.00 sec)
full join
union联合查询自带去重功能
-
兄弟,mysql
不支持 full join,但是我们可以通过骚操作实现 full join ,union 关键字用于连接结果集,并且自动去重 -
tbl_emp 与 tbl_dept 的公共部分 + tbl_emp 表的独有部分 + tbl_dept表的独有部分:将 left join 的结果集和 right join 的结果集使用 union 合并即可
-
select * from tbl_emp e left join tbl_dept d on e.deptId = d.id
union
select * from tbl_emp e right join tbl_dept d on e.deptId = d.id;
mysql> select * from tbl_emp e left join tbl_dept d on e.deptId = d.id
-> union
-> select * from tbl_emp e right join tbl_dept d on e.deptId = d.id;
+------+------+--------+------+----------+--------+
| id | NAME | deptId | id | deptName | locAdd |
+------+------+--------+------+----------+--------+
| 1 | z3 | 1 | 1 | RD | 11 |
| 2 | z4 | 1 | 1 | RD | 11 |
| 3 | z5 | 1 | 1 | RD | 11 |
| 4 | w5 | 2 | 2 | HR | 12 |
| 5 | w6 | 2 | 2 | HR | 12 |
| 6 | s7 | 3 | 3 | MK | 13 |
| 7 | s8 | 4 | 4 | MIS | 14 |
| 8 | s9 | 51 | NULL | NULL | NULL |
| NULL | NULL | NULL | 5 | FD | 15 |
+------+------+--------+------+----------+--------+
9 rows in set (0.00 sec)
full join without common part
-
tbl_emp 表的独有部分 + tbl_dept表的独有部分
-
select * from tbl_emp e left join tbl_dept d on e.deptId = d.id where d.id is null
union
select * from tbl_emp e right join tbl_dept d on e.deptId = d.id where e.deptId is null;
mysql> select * from tbl_emp e left join tbl_dept d on e.deptId = d.id where d.id is null
-> union
-> select * from tbl_emp e right join tbl_dept d on e.deptId = d.id where e.id is null;
+------+------+--------+------+----------+--------+
| id | NAME | deptId | id | deptName | locAdd |
+------+------+--------+------+----------+--------+
| 8 | s9 | 51 | NULL | NULL | NULL |
| NULL | NULL | NULL | 5 | FD | 15 |
+------+------+--------+------+----------+--------+
2 rows in set (0.00 sec)
.
3.1、索引是什么
索引是个什么东东?
-
MySQL官方对索引的定义为:索引(Index)是帮助MySQL高效获取数据的数据结构。可以得到索引的本质:索引是数据结构
-
你可以简单理解为"排好序的快速查找数据结构",即索引 = 排序 + 查找
-
一般来说索引本身占用内存空间也很大,不可能全部存储在内存中,因此索引往往以文件形式存储在硬盘上
-
我们平时所说的索引,如果没有特别指明,都是指B树(多路搜索树,并不一定是二叉树)结构组织的索引。
-
聚集索引,次要索引,覆盖索引,复合索引,前缀索引,唯一索引默认都是使用B+树索引,统称索引。当然,除了B+树这种类型的索引之外,还有哈希索引(hash index)等。
3.2、索引原理
将索引理解为"排好序的快速查找数据结构"
-
在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据,这样就可以在这些数据结构上实现高级查找算法。这种数据结构,就是索引。
-
下图就是一种可能的索引方式示例:
-
左边是数据表,一共有两列七条记录,最左边的十六进制数字是数据记录的物理地址
-
为了
加快col2的查找,可以维护一个右边所示的二叉查找树(索引的数据结构),每个节点分别包含索引键值和一个指向对应数据记录物理地址的指针,这样就可以运用二叉查找在一定的复杂度内获取到相应索引键来获取左侧对应的值,从而快速的检索出符合条件的记录。
3.3、索引优劣势
索引的优势
排好序的快速查找的数据结构:查找 + 排序
-
类似大学图书馆的书目索引,
提高数据检索效率,降低数据库的IO成本 -
通过索引列对数据进行排序,
降低数据排序成本,降低了CPU的消耗
索引的劣势
-
实际上索引也是一张表,该表保存了主键和索引字段,并指向实体表的记录,所以索引列也是要
占用空间的 -
虽然索引大大提高了查询速度,同时却会降低更新表的速度,如果对表INSERT,UPDATE和DELETE。因为更新表时,MySQL不仅要不存数据,还要保存一下索引文件每次更新添加了索引列的字段,都会调整因为更新所带来的键值变化后的索引信息【更新物理地址的同时,索引地址也需要更新】
-
索引只是提高效率的一个因素,如果你的MySQL有大数据量的表,就需要
花时间研究建立优秀的索引,或优化查询语句
3.4、MySQL 索引分类
mysql 索引分类
参考资料:www.cnblogs.com/luyucheng/p…
-
普通索引:是最基本的索引,它没有任何限制,即一个索引只包含单个列,一个表可以有多个单列索引;建议一张表索引不要超过5个,优先考虑复合索引
-
唯一索引:与前面的普通索引类似,不同的就是:索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一
-
主键索引:是一种特殊的唯一索引,一个表只能有一个主键,不允许有空值。一般是在建表的时候同时创建主键索引
-
复合索引:指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用组合索引时遵循最左前缀集合
-
全文索引:主要用来查找文本中的关键字,而不是直接与索引中的值相比较。fulltext索引跟其它索引大不相同,它更像是一个搜索引擎,而不是简单的where语句的参数匹配
3.5、MySQL 索引语法
建立索引的 SQL 语句
- 创建索引:
-
如果是CHAR和VARCHAR类型,length可以小于字段实际长度;
-
如果是BLOB和TEXT类型,必须指定length。
CREATE [UNIQUE] INDEX indexName ON mytable(columnname(length));
' or '
ALTER mytable ADD [UNIQUE] INDEX [indexName] ON(columnname(length));
- 删除索引
DROP INDEX [indexName] ON mytable;
- 查看索引(
\G表示将查询到的横向表格纵向输出,方便阅读)
SHOW INDEX FROM table_name\G
使用 ALTER 命令,有四种方式来添加数据表的索引:
-
ALTER TABLE tbl_name ADD PRIMARY KEY(column_list):该语句添加一个主键,这意味着索引值必须是唯一的,且不能为NULL。 -
ALTER TABLE tbl_name ADD UNIQUE index_name(column_list):这条语句创建索引的值必须是唯一的(除了NULL外,NULL可能会出现多次)。 -
ALTER TABLE tbl_name ADD INDEX index_name(column_list):.添加普通索引,索引值可出现多次。 -
ALTER TABLE tbl_name ADD FULLTEXT index_name(column_list):该语句指定了索引为FULLTEXT,用于全文索引。
带你看看 mysql 索引:Index_type 为 BTREE
mysql> show index from tbl_emp;
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| tbl_emp | 0 | PRIMARY | 1 | id | A | 8 | NULL | NULL | | BTREE | | |
| tbl_emp | 1 | fk_dept_Id | 1 | deptId | A | 8 | NULL | NULL | YES | BTREE | | |
+---------+------------+------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
2 rows in set (0.00 sec)
.
3.6、MySQL 索引结构
3.6.1、Btree 索引
Btree 索引搜索过程
【初始化介绍】
-
一颗 b 树, 浅蓝色的块我们称之为一个磁盘块, 可以看到每个磁盘块包含几个数据项(深蓝色所示) 和指针(黄色所示)
-
如磁盘块 1 包含数据项 17 和 35, 包含指针 P1、 P2、 P3
-
P1 表示小于 17 的磁盘块, P2 表示在 17 和 35 之间的磁盘块, P3 表示大于 35 的磁盘块
-
真实的数据存在于叶子节点和非叶子节点中
【查找过程】
-
如果要查找数据项 29, 那么首先会把磁盘块 1 由磁盘加载到内存, 此时发生一次 IO, 在内存中用二分查找确定 29在 17 和 35 之间, 锁定磁盘块 1 的 P2 指针, 内存时间因为非常短(相比磁盘的 IO) 可以忽略不计
-
通过磁盘块 1的 P2 指针的磁盘地址把磁盘块 3 由磁盘加载到内存, 发生第二次 IO, 29 在 26 和 30 之间, 锁定磁盘块 3 的 P2 指针
-
通过指针加载磁盘块 8 到内存, 发生第三次 IO, 同时内存中做二分查找找到 29, 结束查询, 总计三次 IO。
3.6.2、B+tree 索引
B+tree 索引搜索过程
【B+Tree 与 BTree 的区别】
B-树的:关键字(数据项)和记录【实际数据】是放在一起的;
B+树的:非叶子节点中只有关键字和指向下一个节点的索引, 记录【实际数据】只放在叶子节点中。
【B+Tree 与 BTree 的查找过程】
-
在 B 树中, 越靠近根节点的记录查找时间越快, 只要找到关键字即可确定记录的存在; 而 B+ 树中每个记录的查找时间基本是一样的, 都需要从根节点走到叶子节点, 而且在叶子节点中还要再比较关键字。
-
从这个角度看 B 树的性能好像要比 B+ 树好, 而在实际应用中却是 B+ 树的性能要好些。 因为 B+ 树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比 B 树多, 树高比 B 树小, 这样带来的好处是减少磁盘访问次数。
-
尽管 B+ 树找到一个记录所需的比较次数要比 B 树多, 但是一次磁盘访问的时间相当于成百上千次内存比较的时间, 因此实际中B+ 树的性能可能还会好些, 而且 B+树的叶子节点使用指针连接在一起, 方便顺序遍历(范围搜索), 这也是很多数据库和文件系统使用 B+树的缘故。
【性能提升】
真实的情况是, 3 层的 B+ 树可以表示上百万的数据, 如果上百万的数据查找只需要三次 IO, 性能提高将是巨大的,如果没有索引, 每个数据项都要发生一次 IO, 那么总共需要百万次的 IO, 显然成本非常非常高。
【思考: 为什么说 B+树比 B-树更适合实际应用中操作系统的文件索引和数据库索引?】
-
B+树的磁盘读
写代价更低:B+树的内部结点并没有指向关键字具体信息的指针。 因此其内部结点相对 B 树更小。 如果把所有同一内部结点的关键字存放在同一盘块中, 那么盘块所能容纳的关键字数量也越多。 一次性读入内存中的需要查找的关键字也就越多。 相对来说IO 读写次数低。 -
B+树的
查询效率更加稳定:由于非终结点并不是最终指向文件内容的结点, 而只是叶子结点中关键字的索引。 所以任何关键字的查找必须走一条从根结点到叶子结点的路。 所有关键字查询的路径长度相同, 导致每一个数据的查询效率相当。
3.7、何时需要建索引
哪些情况下适合建立索引
-
主键自动建立唯一索引
-
频繁作为查询的条件的字段应该创建索引
-
查询中与其他表关联的字段,外键关系建立索引
-
频繁更新的字段不适合创建索引
-
Where 条件里用不到的字段不创建索引
-
单间/组合索引的选择问题,Who?(在高并发下倾向创建组合索引)
-
查询中排序的字段,排序字段若通过索引去访问将大大提高排序的速度
-
查询中统计或者分组字段
哪些情况不要创建索引
-
表记录太少
-
经常增删改的表
-
数据重复且分布平均的表字段,因此应该只为经常查询和经常排序的数据列建立索引。注意,如果某个数据列包含许多重复的内容,为它建立索引就没有太大的实际效果。
案例分析:
-
假如一个表有10万行记录,有一个字段A只有T和F两种值,且每个值的分布概率大约为50%,那么对这种表A字段建索引一般不会提高数据库的查询速度。
-
索引的选择性是指索引列中不同值的数目与表中记录数的比。如果一个表中有2000条记录,表索引列有1980个不同的值,那么这个索引的选择性就是1980/2000=0.99。
-
一个索引的选择性越接近于1,这个索引的效率就越高。
.
4.1、性能优化概述
MySQL Query Optimizer 的作用
-
MySQL 中有专门负责优化SELECT语句的优化器模块,主要功能:通过计算分析系统中收集到的统计信息,为客户端请求的Query提供他认为最优的执行计划(MySQL认为最优的数据检索方式,但不见得是DBA认为是最优的,这部分最耗费时间)
-
当客户端向MySQL 请求一条Query,命令解析器模块完成请求分类,区别出是SELECT并转发给MySQL Query Optimizer时,MySQL Query Optimizer 首先会对整条Query进行优化,处理掉一些常量表达式的预算,直接换算成常量值。并对Query中的查询条件进行简化和转换,如去掉一些无用或显而易见的条件、结构调整等。然后分析 Query中的Hint信息(如果有),看显示Hint信息是否可以完全确定该Query的执行计划。如果没有Hint 或Hint 信息还不足以完全确定执行计划,则会读取所涉及对象的统计信息,根据Query进行写相应的计算分析,然后再得出最后的执行计划。
MySQL 常见瓶颈
-
CPU 瓶颈:CPU在饱和的时候一般发生在数据装入在内存或从磁盘上读取数据时候
-
IO 瓶颈:磁盘I/O瓶颈发生在装入数据远大于内存容量时
-
服务器硬件的性能瓶颈:top、free、iostat和vmstat来查看系统的性能状态
4.2、Explain 概述
Explain
是什么?Explain 是查看执行计划
-
使用EXPLAIN关键字可以模拟优化器执行SQL语句,从而知道MySQL是如何处理你的SQL语句的。分析你的查询语句或是结构的性能瓶颈
能干嘛?
-
表的读取顺序(id 字段)
-
数据读取操作的操作类型(select_type 字段)
-
哪些索引可以使用(possible_keys 字段)
-
哪些索引被实际使用(keys 字段)
-
表之间的引用(ref 字段)
-
每张表有多少行被优化器查询(rows 字段)
最后
为什么我不完全主张自学? ①平台上的大牛基本上都有很多年的工作经验了,你有没有想过之前行业的门槛是什么样的,现在行业门槛是什么样的?以前企业对于程序员能力要求没有这么高,甚至十多年前你只要会写个“Hello World”,你都可以入门这个行业,所以以前要入门是完全可以入门的。 ②现在也有一些优秀的年轻大牛,他们或许也是自学成才,但是他们一定是具备优秀的学习能力,优秀的自我管理能力(时间管理,静心坚持等方面)以及善于发现问题并总结问题。 如果说你认为你的目标十分明确,能做到第②点所说的几个点,以目前的市场来看,你才真正的适合去自学。
除此之外,对于绝大部分人来说,报班一定是最好的一种快速成长的方式。但是有个问题,现在市场上的培训机构质量参差不齐,如果你没有找准一个好的培训班,完全是浪费精力,时间以及金钱,这个需要自己去甄别选择。
我个人建议线上比线下的性价比更高,线下培训价格基本上没2W是下不来的,线上教育现在比较成熟了,此次疫情期间,学生基本上都感受过线上的学习模式。相比线下而言,线上的优势以我的了解主要是以下几个方面: ①价格:线上的价格基本上是线下的一半; ②老师:相对而言线上教育的师资力量比线下更强大也更加丰富,资源更好协调; ③时间:学习时间相对而言更自由,不用裸辞学习,适合边学边工作,降低生活压力; ④课程:从课程内容来说,确实要比线下讲的更加深入。
应该学哪些技术才能达到企业的要求?(下图总结)
相关阅读docs.qq.com/doc/DSmxTbFJ1cmN1R2dB