×

mysql数据库优化面试 数据库

mysql数据库优化面试(想从事数据库相关的工作,迷惑中)

admin admin 发表于2022-09-05 00:54:39 浏览92 评论0

抢沙发发表评论

本文目录

想从事数据库相关的工作,迷惑中


数据库方面的工作分为两类:
一类是利用SQL做开发,这个是对数据库的应用。一般来说,都是编程人员,利用接口比如JDBC调用数据库的SQL来做查询。这种工作重点还是在编程上。因为涉及到的数据库方面的知识并不算多。说白了,就是和“数据库编码相关的程序员”。
另一类是数据库管理人员,主要负责数据库的备份,日常维护,代码优化等等。相对来说对数据库方面的知识要求较高,对技术要求也较高。也就是所谓的DBA。
大二、大三时候,其实多数人对自己将来的规划都不明确。都认为自己将来会从事很多编程的工作。因为所学的科目大多和编程有关系。可实际上最终真正从事编程的人最多只是55开。所以你不必过早的把自己定位成一个编程人员。
程序开发是很辛苦的,而且很伤身体,做不了太久。我建议你多拓宽自己的思维,将来有很多其他的机会,比如BA,比如架构师,比如QA等等。
至于你说的,你们的课程和数据库有关。那是必然的,任何计算机相关专业都必须学到数据库。但“面向对象程序设计”和数据库的关系,就不是很大了。
你要抓住计算机相关专业的几门核心课程:数据结构,操作系统,组成原理等等。这些东西将来才是真正帮助你的东西。至于如何编程,考什么证书,这些都是次要的。我坦白的跟你讲,这些东西你工作之后有大把的时间去学。而基础那时候就难补了。所以你将来能走多远,很大程度上是看你现在的基础怎么样。那些“看起来没什么用”的课,将来会对你有很大的帮助。
-------------------------------
综上,你过早的把自己定位在一个数据库开发人员,这本就是错误的,打好基础才是重点。计算机不只是编程,而编程未必像你想的那么有趣。
oracle数据库也好,db2数据库也罢,都只不过是别人提供的一种软件而已。你只要掌握了数据库基本的增查删改语句,对于将来数据库的开发就基本够用了。至于优化什么的,是要到具体的工作中去学。更何况,你将来即使是和数据库相关的开发,也是主要集中在编程上而非数据库上。

php新手在找工作时目标是选大公司、小公司还是其他哪些分司找到工作的概率会大些


这么跟你说吧,公司可能会因为以下原因招聘一个人:

  1. 公司非常缺人,那么不管你水平与否,只要面试觉得差不多,那么就会要你去上班。

  2. 公司的运作已经比较成熟,有能力带领新人(只限大公司),一般这样的公司,薪水不会低,但是你要做的事情也就不会很广泛,可能就局限于某一部分(比如操作数据库,大公司分工明确,写数据库的就专门负责数据库建立,数据库优化,写存储过程、触发器等等,那么就不会要你去写php的代码了),这样的话,你能需要的东西就不会很多,很广泛,但是压力也相对来说,要稍微小一点。 但是这样的大公司绝对不会缺你这样的人,那么招聘的时候,肯定是学历高的优先、有经验作品的优先、甚至长相好的优先等,都是有可能的。-mysql数据库优化面试

  3. 小公司,既然是小公司,那么人数必然是不多,那么同样的事情,分配到小公司的少数人手中,你需要做的事情就很多(WEB网页设计,CSS+DIV,要能兼容浏览器、数据库建立(mysql、mssql、sqlite、oracle等等)、数据库优化、存储过程、php代码(包含框架,thinkphp、ci、zend、yii、cakephp等等)、服务器配置(一般是IIS)、PHP环境搭建(xampp、wampserver、mysql+apache等)、jquery、ajax、json等)。这些东西也许你很多是一窍不通,甚至小公司也没有人能去教你,完全靠你自己去摸索(很多人坚持不下来的)。-数据库

        但是小公司能坚持下来几年的人,去大公司是绝对没有问题,但是大公司呆过几年的人,小公司的事情还不一定能干的来。

    4.所以小公司招人,肯定是要有经验的,哪怕你就是硕士、博士毕业,你事情干不来,他仍然会要一个只有高中毕业,但是能干的来事情的人。

    5. 总结就是:去大公司打工,白领,未来方向一般是:高级打工仔。  去小公司发展,未来方向一般是:管理阶层,自己开新公司。

 

但是你能否找到工作,与大公司或者小公司无关,跟你自己的选择跟你的能力有关。


面试中常问:mysql数据库做哪些优化也提高mysql性能


在开始演示之前,我们先介绍下两个概念。

概念一,数据的可选择性基数,也就是常说的cardinality值。

查询优化器在生成各种执行计划之前,得先从统计信息中取得相关数据,这样才能估算每步操作所涉及到的记录数,而这个相关数据就是cardinality。简单来说,就是每个值在每个字段中的唯一值分布状态。

比如表t1有100行记录,其中一列为f1。f1中唯一值的个数可以是100个,也可以是1个,当然也可以是1到100之间的任何一个数字。这里唯一值越的多少,就是这个列的可选择基数。

那看到这里我们就明白了,为什么要在基数高的字段上建立索引,而基数低的的字段建立索引反而没有全表扫描来的快。当然这个只是一方面,至于更深入的探讨就不在我这篇探讨的范围了。

概念二,关于HINT的使用。

这里我来说下HINT是什么,在什么时候用。

HINT简单来说就是在某些特定的场景下人工协助MySQL优化器的工作,使她生成最优的执行计划。一般来说,优化器的执行计划都是最优化的,不过在某些特定场景下,执行计划可能不是最优化。

比如:表t1经过大量的频繁更新操作,(UPDATE,DELETE,INSERT),cardinality已经很不准确了,这时候刚好执行了一条SQL,那么有可能这条SQL的执行计划就不是最优的。为什么说有可能呢?-mysql数据库优化面试

来看下具体演示

譬如,以下两条SQL,

  • A:

  • select * from t1 where f1 = 20;

  • B:

  • select * from t1 where f1 = 30;

  • 如果f1的值刚好频繁更新的值为30,并且没有达到MySQL自动更新cardinality值的临界值或者说用户设置了手动更新又或者用户减少了sample page等等,那么对这两条语句来说,可能不准确的就是B了。-数据库

    这里顺带说下,MySQL提供了自动更新和手动更新表cardinality值的方法,因篇幅有限,需要的可以查阅手册。

    那回到正题上,MySQL 8.0 带来了几个HINT,我今天就举个index_merge的例子。

    示例表结构:

  • mysql》 desc t1;+------------+--------------+------+-----+---------+----------------+| Field      | Type         | Null | Key | Default | Extra          |+------------+--------------+------+-----+---------+----------------+| id         | int(11)      | NO   | PRI | NULL    | auto_increment || rank1      | int(11)      | YES  | MUL | NULL    |                || rank2      | int(11)      | YES  | MUL | NULL    |                || log_time   | datetime     | YES  | MUL | NULL    |                || prefix_uid | varchar(100) | YES  |     | NULL    |                || desc1      | text         | YES  |     | NULL    |                || rank3      | int(11)      | YES  | MUL | NULL    |                |+------------+--------------+------+-----+---------+----------------+7 rows in set (0.00 sec)

  • 表记录数:

  • mysql》 select count(*) from t1;+----------+| count(*) |+----------+|    32768 |+----------+1 row in set (0.01 sec)

  • 这里我们两条经典的SQL:

  • SQL C:

  • select * from t1 where rank1 = 1 or rank2 = 2 or rank3 = 2;

  • SQL D:

  • select * from t1 where rank1 =100  and rank2 =100  and rank3 =100;

  • 表t1实际上在rank1,rank2,rank3三列上分别有一个二级索引。

    那我们来看SQL C的查询计划。

    显然,没有用到任何索引,扫描的行数为32034,cost为3243.65。

  • mysql》 explain  format=json select * from t1  where rank1 =1 or rank2 = 2 or rank3 = 2\G*************************** 1. row ***************************EXPLAIN: {  “query_block“: {    “select_id“: 1,    “cost_info“: {      “query_cost“: “3243.65“    },    “table“: {      “table_name“: “t1“,      “access_type“: “ALL“,      “possible_keys“: [        “idx_rank1“,        “idx_rank2“,        “idx_rank3“      ],      “rows_examined_per_scan“: 32034,      “rows_produced_per_join“: 115,      “filtered“: “0.36“,      “cost_info“: {        “read_cost“: “3232.07“,        “eval_cost“: “11.58“,        “prefix_cost“: “3243.65“,        “data_read_per_join“: “49K“      },      “used_columns“: [        “id“,        “rank1“,        “rank2“,        “log_time“,        “prefix_uid“,        “desc1“,        “rank3“      ],      “attached_condition“: “((`ytt`.`t1`.`rank1` = 1) or (`ytt`.`t1`.`rank2` = 2) or (`ytt`.`t1`.`rank3` = 2))“    }  }}1 row in set, 1 warning (0.00 sec)

  • 我们加上hint给相同的查询,再次看看查询计划。

    这个时候用到了index_merge,union了三个列。扫描的行数为1103,cost为441.09,明显比之前的快了好几倍。

  • mysql》 explain  format=json select /*+ index_merge(t1) */ * from t1  where rank1 =1 or rank2 = 2 or rank3 = 2\G*************************** 1. row ***************************EXPLAIN: {  “query_block“: {    “select_id“: 1,    “cost_info“: {      “query_cost“: “441.09“    },    “table“: {      “table_name“: “t1“,      “access_type“: “index_merge“,      “possible_keys“: [        “idx_rank1“,        “idx_rank2“,        “idx_rank3“      ],      “key“: “union(idx_rank1,idx_rank2,idx_rank3)“,      “key_length“: “5,5,5“,      “rows_examined_per_scan“: 1103,      “rows_produced_per_join“: 1103,      “filtered“: “100.00“,      “cost_info“: {        “read_cost“: “330.79“,        “eval_cost“: “110.30“,        “prefix_cost“: “441.09“,        “data_read_per_join“: “473K“      },      “used_columns“: [        “id“,        “rank1“,        “rank2“,        “log_time“,        “prefix_uid“,        “desc1“,        “rank3“      ],      “attached_condition“: “((`ytt`.`t1`.`rank1` = 1) or (`ytt`.`t1`.`rank2` = 2) or (`ytt`.`t1`.`rank3` = 2))“    }  }}1 row in set, 1 warning (0.00 sec)

  • 我们再看下SQL D的计划:

  • 不加HINT,

  • mysql》 explain format=json select * from t1 where rank1 =100 and rank2 =100 and rank3 =100\G*************************** 1. row ***************************EXPLAIN: {  “query_block“: {    “select_id“: 1,    “cost_info“: {      “query_cost“: “534.34“    },    “table“: {      “table_name“: “t1“,      “access_type“: “ref“,      “possible_keys“: [        “idx_rank1“,        “idx_rank2“,        “idx_rank3“      ],      “key“: “idx_rank1“,      “used_key_parts“: [        “rank1“      ],      “key_length“: “5“,      “ref“: [        “const“      ],      “rows_examined_per_scan“: 555,      “rows_produced_per_join“: 0,      “filtered“: “0.07“,      “cost_info“: {        “read_cost“: “478.84“,        “eval_cost“: “0.04“,        “prefix_cost“: “534.34“,        “data_read_per_join“: “176“      },      “used_columns“: [        “id“,        “rank1“,        “rank2“,        “log_time“,        “prefix_uid“,        “desc1“,        “rank3“      ],      “attached_condition“: “((`ytt`.`t1`.`rank3` = 100) and (`ytt`.`t1`.`rank2` = 100))“    }  }}1 row in set, 1 warning (0.00 sec)

  • 加了HINT,

  • mysql》 explain format=json select /*+ index_merge(t1)*/ * from t1 where rank1 =100 and rank2 =100 and rank3 =100\G*************************** 1. row ***************************EXPLAIN: {  “query_block“: {    “select_id“: 1,    “cost_info“: {      “query_cost“: “5.23“    },    “table“: {      “table_name“: “t1“,      “access_type“: “index_merge“,      “possible_keys“: [        “idx_rank1“,        “idx_rank2“,        “idx_rank3“      ],      “key“: “intersect(idx_rank1,idx_rank2,idx_rank3)“,      “key_length“: “5,5,5“,      “rows_examined_per_scan“: 1,      “rows_produced_per_join“: 1,      “filtered“: “100.00“,      “cost_info“: {        “read_cost“: “5.13“,        “eval_cost“: “0.10“,        “prefix_cost“: “5.23“,        “data_read_per_join“: “440“      },      “used_columns“: [        “id“,        “rank1“,        “rank2“,        “log_time“,        “prefix_uid“,        “desc1“,        “rank3“      ],      “attached_condition“: “((`ytt`.`t1`.`rank3` = 100) and (`ytt`.`t1`.`rank2` = 100) and (`ytt`.`t1`.`rank1` = 100))“    }  }}1 row in set, 1 warning (0.00 sec)

  • 对比下以上两个,加了HINT的比不加HINT的cost小了100倍。

    总结下,就是说表的cardinality值影响这张的查询计划,如果这个值没有正常更新的话,就需要手工加HINT了。相信MySQL未来的版本会带来更多的HINT。


为什么面试都会问下很基础的知识,而实际工作中这些基础根本用不到


中国的软件开发行业,存在一个搞笑的现象,招聘者为了抬高自己的面子,把面试题出得天花乱坠,而实际上他们做的项目却是无比弱智.
仔细分析那些题目,你会发现漏洞百出,破绽百出.以java开发面试,举例如下:
1.关于框架
招聘者:你平时常用哪些框架?
应聘者:在没有甲方和项目经理刻意要求的情况下,基本上不用框架,自己写原生.
招聘者:但是框架可以解决很多问题,比如,spring的面向切面的思想有助于使代码具有更好的可读性和易维护性.
应聘者:如果框架确实能够有效地解决我的问题,我会愿意去学习并且使用它们的.可是,在我之前的开发经历中,还没有遇到过特别棘手的问题.
招聘者:...
2.关于高并发
招聘者:高并发算不算棘手的问题?你怎么应对高并发?
应聘者:线程池加同步队列加拒绝策略,以保护服务器不会瘫痪.
招聘者:你为什么不使用redis来处理高并发?
应聘者:既然java自己已经有能力来解决这个问题了,就没有必要再去求助于别的东西了.
招聘者:...
3.关于数据库
招聘者:你做过mysql优化吗?
应聘者:我不需要做mysql优化.因为mysql+php的时代已经过去了,现在应该属于oracle+java的时代.除非贵公司还做外包项目而不是自主产品.
招聘者:但是这并不意味着java就不能与mysql相配合.
应聘者:我看到甲骨文官方已经明文规定了,java的最佳搭档是oracle,而不是mysql.这是官方的明文规定.
招聘者:...
4.关于即时通信
招聘者:你了解环信或者融云等即时通信吗?
应聘者:听说过环信,没有接触过它.没有听说过融云.
招聘者:那么当你需要主动推送消息的时候,怎么办?
应聘者:开socket长连接,一切实时通信全是基于tcp/ip协议或者ws协议的长连接机制.
招聘者:...
5.关于前端
招聘者:你熟悉前端的js吗?
应聘者:熟悉,js是一种基于对象的语言.
招聘者:为什么是基于对象而不是面向对象?
应聘者:java是面向对象的,其三大特性为:封装,继承,多态.而js是基于对象的,其两大特性为:原型,闭包.这两者完全不是一回事.
招聘者:...
笔者的结论:表面上面试官提出许多足以建造宇宙飞船的问题,现实却是你到了公司里顶多在生产某个不起眼儿的螺丝.当你再去反思那些既可笑又可悲的面试题时,你便会明白那些题目本身是漏洞百出,甚至所谓的架构师的水平根本不如你.他能面试你,而你不能面试他,原因不在于他掌握了技术,而在于他掌握了权力.
每一道题皆反映了该公司当前的状态和困境.他过于强调依赖框架,中间件和第三方服务商,是因为他对于java底层的反射委托调度原理不精通.他使用mysql而不是oracle,是因为此公司的资金不充足,无法为自己的软件产品挑选真正优秀且强壮的数据库.他把面向对象和基于对象两个概念混淆了,是因为他从来没有悟透本质的程序语言和脚本语言的核心内涵.
综上所述,求职者千万不能被企业给糊弄了.归根结底一句话:只要你自己充满了信心,走南闯北都不怕.
-mysql数据库优化面试