mysql索引优化系列(一)

news2024/11/15 5:35:42

一、不常见的索引失效场景

1、举例

还是之前的member会员记录表,往里面插入十万条数据

drop procedure if exists insert_emp;
CREATE PROCEDURE insert_emp () BEGIN
	DECLARE
		i INT;
	
	SET i = 1;
	WHILE
			( i <= 100000 ) DO
			INSERT INTO member ( NAME, age, address, create_time )
		VALUES
			( CONCAT( 'gaorufeng', i ), i, 'test', NOW() );
		
		SET i = i + 1;
		
	END WHILE;
END;


call insert_emp();
  •  联合索引有些可能不会走索引
KEY `idx_name_age_address` (`name`,`age`,`address`)
EXPLAIN SELECT * FROM member WHERE name > 'gaorufeng' AND age = 22 AND address ='guangzhou';
EXPLAIN SELECT * FROM member WHERE name > 'test' AND age = 22 AND address ='guangzhou';

据我推测,因为在底层联合索引树上都含有gaorufeng字符,mysql底层认为匹配的数据比较多,需要回表的次数也多,所以最终没有用到;而使用test字符做name条件时,mysql觉得可能找到结果集比较少,需要回表的次数也少,所以最终选择用联合索引的name字段

  • 强制走索引和忽略索引
EXPLAIN SELECT * FROM member force index(idx_name_age_address) WHERE name > 'gaorufeng' AND age = 22 AND address ='guangzhou';
EXPLAIN SELECT * FROM member ignore index(idx_name_age_address)WHERE name > 'test' AND age = 22 AND address ='guangzhou';

第一条sql: 一般情况下我们认为走索引一定会比不走索引要快,而强制走索引其实不然,mysql底层是通过分析选择走不走索引,前面已经讲到,联合索引过滤的结果集越大,回表次数越多,最后还不如全表扫描;

第二条sql:系统用了索引而强制不走索引,一般没人会这么做

  • 使用覆盖索引优化
EXPLAIN SELECT id,name,age,address FROM member WHERE name > 'gaorufeng' AND age = 22 AND address ='guangzhou';

把所有的查询字段都在联合索引树上找到

  • in和or在数据量大的情况下会走索引
EXPLAIN SELECT * FROM member WHERE (name = 'test1' or name = 'test2') AND age = 22 AND address ='guangzhou';
EXPLAIN SELECT * FROM member_copy WHERE (name = 'test1' or name = 'test2') AND age = 22 AND address ='guangzhou';

EXPLAIN SELECT * FROM member WHERE name in ( 'test1', 'test2') AND age = 22 AND address ='guangzhou';
EXPLAIN SELECT * FROM member_copy WHERE name  in ('test1', 'test2') AND age = 22 AND address ='guangzhou';

这种数据量大情况会走索引,但是in和or条件不要太多了,如果太多,那联合索引过滤的结果集大,回表次数多也不会走索引;member_copy表数据量少全表扫描快

  • like 'x%'可能野不会用到索引
EXPLAIN SELECT * FROM member WHERE name like 'gaorufeng%' AND age = 22 AND address ='guangzhou';
EXPLAIN SELECT * FROM member WHERE name like 'test%' AND age = 22 AND address ='guangzhou';

还是和之前的大于一样,如果在联合索引树上匹配了很多数据,那么回表次数过多就会走全表扫描;而如果找到数量较少,回表次数少,就会用到索引;

另外我觉得联合索引左边字段范围查询,下一个字段是无序的,;而like 'x%'已经确定了前缀,mysql底层也会根据前缀做一下排序,所以下一个字段是有序的,所以范围查询后面的字段用不到索引,like 'x%'可以用到

2、索引下推(Index Condition Pushdown,ICP)

mysql5.6引入的索引下推,旨在减少联合索引回表次数

EXPLAIN SELECT * FROM member WHERE name like 'gaorufeng%' AND age = 22 AND address ='guangzhou';

mysql5.6版本之前的执行过程:首先根据name like 'gaorufeng%'条件找到结果集直接回表到主键索引树上,找到结果集后再判断age、address是否相等

mysql5.6版本和之后版本的执行过程:还是跟之前一样根据like查找,这个时候它会再根据联合索引后面的字段条件筛选,然后回表,这样可以过滤掉一些结果集,减少回表次数,提高查询效率(如果在开发过程中联合索引后面字段用到了索引,就有可能是mysql底层使用了索引下推)

二、mysql选择索引

1、索引合并机制

在mysql5.0之前一个表的一次查询只能有一个索引被用到,自mysql5.1版本开始,引入了index merge技术,当一个查询用到多个索引,mysql底层会同时在两颗或者多颗索引树上查询结果集后,把主键id值汇总取交集,然后回表,这样可以减少不必要的回表,这里不做赘述了,我好累

2、trace工具

EXPLAIN select * from member where name > 'gaorufeng';#查询所有数据 需要联合索引树上进行范围查询结果集回表 回表次数多因而选择全表扫描
EXPLAIN select id,name,age,address from member where name > 'gaorufeng';#查询字段数据在联合索引上都有 不需要回表所以走了索引
EXPLAIN select * from member where name > 'test';#mysql觉得通过test查询出来的结果集较少 回表次数较少 所以还是用了索引

 用trace工具分析:

set session optimizer_trace="enabled=on",end_markers_in_json=on; #开启trace
select * from member where name > 'gaorufeng' order by address;
SELECT * FROM information_schema.OPTIMIZER_TRACE;

 复制TRACE字段的值,展示如下:

{
  "steps": [
    {
      "join_preparation": { /* 准备阶段 */
        "select#": 1,
        "steps": [
          {
            "expanded_query": "/* select#1 */ select `member`.`id` AS `id`,`member`.`name` AS `name`,`member`.`age` AS `age`,`member`.`address` AS `address`,`member`.`create_time` AS `create_time` from `member` where (`member`.`name` > 'gaorufeng') order by `member`.`address`"
          }
        ] /* steps */
      } /* join_preparation */
    },
    {
      "join_optimization": { /* 优化阶段 */
        "select#": 1,
        "steps": [
          {
            "condition_processing": { /* 条件处理 */
              "condition": "WHERE",
              "original_condition": "(`member`.`name` > 'gaorufeng')",
              "steps": [
                {
                  "transformation": "equality_propagation",
                  "resulting_condition": "(`member`.`name` > 'gaorufeng')"
                },
                {
                  "transformation": "constant_propagation",
                  "resulting_condition": "(`member`.`name` > 'gaorufeng')"
                },
                {
                  "transformation": "trivial_condition_removal",
                  "resulting_condition": "(`member`.`name` > 'gaorufeng')"
                }
              ] /* steps */
            } /* condition_processing */
          },
          {
            "table_dependencies": [ /* 表依赖数据 */
              {
                "table": "`member`",
                "row_may_be_null": false,
                "map_bit": 0,
                "depends_on_map_bits": [
                ] /* depends_on_map_bits */
              }
            ] /* table_dependencies */
          },
          {
            "ref_optimizer_key_uses": [
            ] /* ref_optimizer_key_uses */
          },
          {
            "rows_estimation": [ /* 估算扫描的行数,查询的代价 */
              {
                "table": "`member`",
                "range_analysis": {
                  "table_scan": { /* 如果全表扫描的话,可能需要扫描多少行 */
                    "rows": 97393, /* 估算的扫描行 */
                    "cost": 19834 /* 估算的扫描成本 */
                  } /* table_scan */,
                  "potential_range_indices": [ /* 表中可能用到的索引 */
                    {
                      "index": "PRIMARY", /* 索引名称 */
                      "usable": false, /* 是否使用 */
                      "cause": "not_applicable" /* 原因 */
                    },
                    {
                      "index": "idx_name_age_address",
                      "usable": true, /* 可能使用二级索引 */
                      "key_parts": [
                        "name",
                        "age",
                        "address",
                        "id"
                      ] /* key_parts */
                    }
                  ] /* potential_range_indices */,
                  "setup_range_conditions": [ /* 如果有可下推的条件,则带条件考虑范围查询 */
                  ] /* setup_range_conditions */,
                  "group_index_range": { /* 当使用了GROUP BY或DISTINCT时,是否有合适的索引 */
                    "chosen": false,
                    "cause": "not_group_by_or_distinct" /* 原因 */
                  } /* group_index_range */,
                  "analyzing_range_alternatives": { /* 分析range范围查询索引使用成本 */
                    "range_scan_alternatives": [ /* 范围扫描选择 */
                      {
                        "index": "idx_name_age_address", /* 索引名 */
                        "ranges": [ /* range扫描的条件范围 */
                          "gaorufeng < name"
                        ] /* ranges */,
                        "index_dives_for_eq_ranges": true,
                        "rowid_ordered": false, /* 使用该索引获取的记录是否按照主键排序 */
                        "using_mrr": false,
                        "index_only": false, /* 表示是否使用了覆盖索引 */
                        "rows": 48696, /* 索引扫描行数 */
                        "cost": 58436, /* 索引扫描成本 */
                        "chosen": false, /* 是否使用该索引 */
                        "cause": "cost"
                      }
                    ] /* range_scan_alternatives */,
                    "analyzing_roworder_intersect": { /* 分析是否使用了索引合并,如果未使用,则会给出cause */
                      "usable": false,
                      "cause": "too_few_roworder_scans"
                    } /* analyzing_roworder_intersect */
                  } /* analyzing_range_alternatives */
                } /* range_analysis */
              }
            ] /* rows_estimation */
          },
          {
            "considered_execution_plans": [ /* 对比各个扫描计划的开销,选择相对最优的执行计划 */
              {
                "plan_prefix": [
                ] /* plan_prefix */,
                "table": "`member`",
                "best_access_path": { /* 最优的访问路径 */
                  "considered_access_paths": [ /* 最终选择的访问路径 */
                    {
                      "access_type": "scan", /* 访问类型:为scan,全表扫描 */
                      "rows": 48696,
                      "cost": 19832,
                      "chosen": true, /* 确认选择 */
                      "use_tmp_table": true
                    }
                  ] /* considered_access_paths */
                } /* best_access_path */,
                "cost_for_plan": 19832,
                "rows_for_plan": 48696,
                "sort_cost": 48696,
                "new_cost_for_plan": 68528,
                "chosen": true
              }
            ] /* considered_execution_plans */
          },
          {
            "attaching_conditions_to_tables": {
              "original_condition": "(`member`.`name` > 'gaorufeng')",
              "attached_conditions_computation": [
              ] /* attached_conditions_computation */,
              "attached_conditions_summary": [
                {
                  "table": "`member`",
                  "attached": "(`member`.`name` > 'gaorufeng')"
                }
              ] /* attached_conditions_summary */
            } /* attaching_conditions_to_tables */
          },
          {
            "clause_processing": {
              "clause": "ORDER BY",
              "original_clause": "`member`.`address`",
              "items": [
                {
                  "item": "`member`.`address`"
                }
              ] /* items */,
              "resulting_clause_is_simple": true,
              "resulting_clause": "`member`.`address`"
            } /* clause_processing */
          },
          {
            "refine_plan": [
              {
                "table": "`member`",
                "access_type": "table_scan"
              }
            ] /* refine_plan */
          },
          {
            "reconsidering_access_paths_for_index_ordering": {
              "clause": "ORDER BY",
              "index_order_summary": {
                "table": "`member`",
                "index_provides_order": false,
                "order_direction": "undefined",
                "index": "unknown",
                "plan_changed": false
              } /* index_order_summary */
            } /* reconsidering_access_paths_for_index_ordering */
          }
        ] /* steps */
      } /* join_optimization */
    },
    {
      "join_execution": { /* 执行阶段 */
        "select#": 1,
        "steps": [
          {
            "filesort_information": [
              {
                "direction": "asc",
                "table": "`member`",
                "field": "address"
              }
            ] /* filesort_information */,
            "filesort_priority_queue_optimization": {
              "usable": false,
              "cause": "not applicable (no LIMIT)"
            } /* filesort_priority_queue_optimization */,
            "filesort_execution": [
            ] /* filesort_execution */,
            "filesort_summary": {
              "rows": 100000,
              "examined_rows": 100000,
              "number_of_tmp_files": 75,
              "sort_buffer_size": 262052,
              "sort_mode": "<sort_key, additional_fields>"
            } /* filesort_summary */
          }
        ] /* steps */
      } /* join_execution */
    }
  ] /* steps */
}

mysql底层cost成本分析,全表扫描比索引成本低,所以选择了全表扫描

set session optimizer_trace="enabled=off";#关闭trace

三、mysql常见索引优化

1、order by和group by优化

explain select * from member where name = 'gaorufeng' order by age;

因为联合索引name字段已经确认,age肯定就是有序的,可以用到索引排序

explain select * from member where name = 'gaorufeng' order by address;

 因为跳过联合索引age字段选择用address字段排序,用到了文件排序;

文件排序:因为address被确定是无序的所以无法在索引树上进行排序,只能先将一部分结果集放到文件中,另一部分结果集排好序之后再把文件加载到内存中进行排序,这样就会比较慢了

索引排序:在建索引树的时候就已经排好了序,这样就只要过滤结果集就可以了

explain select * from member where name = 'gaorufeng' order by age,address;

联合索引前面name索引字段已经确定,后面的age,address都是有序的,就跟构建索引树一样(不要去想address是无序的,你要想age都排好了,构建索引树也是根据上一个字段排序下一个字段,所以是有序的),所以没有用到文件排序;至于where后面如果再加条件的话,mysql底层会根据cost成本计算回表次数来决定要不要使用索引

explain select * from member where name = 'gaorufeng' order by address,age;

联合索引排序这种,如果排序字段位置调换会导致使用文件排序,因为已经跳过了age字段

explain select * from member where name = 'gaorufeng' and age = 18 order by address,age;

 这种拿屁股想都能想到,name和age都已经确定了,age参不参与排序已经不重要了,最后一个address肯定有序的

explain select * from member where name = 'gaorufeng' order by address asc,age desc;

联合索引基本上都是靠前面的一个字段来确定下一个字段在索引树上的顺序,所以顺序不可能倒过来,用到了文件排序,mysql8.0引入降序索引,可以指定联合索引排序是asc、desc

explain select * from member where name = 'gaorufeng' or name = 'test' order by age,address;
explain select * from member where name in ('gaorufeng','test') order by age,address;
explain select * from member where name > 'gaorufeng' order by age,address;
explain select * from member where name like 'test%' order by age,address;

联合索引中用了or、in、范围查找、like,再用下一个字段排序都会出现文件排序,你把address去掉也是一样的;照这样来说,其实用了这些后面字段都是无序的,你把它们都用覆盖索引也是一样的,至于where为什么用了索引,我认为是虽然用了or、in、范围查找、like,但是索引树上筛选出来的结果主键id少,回表次数少,所以用了索引,而排序,你只能用name排序

证明用覆盖索引也没用:


explain select id,name,age,address from member where name = 'gaorufeng' or name = 'test' order by age;
explain select id,name,age,address from member where name in ('gaorufeng','test') order by age;
explain select id,name,age,address from member where name > 'gaorufeng' order by age;
explain select id,name,age,address from member where name like 'test%' order by age;

explain select * from member where name = 'gaorufeng' or name = 'test' order by name;
explain select * from member where name in ('gaorufeng','test') order by name;
explain select * from member where name > 'gaorufeng' order by name;
explain select * from member where name like 'test%' order by name;

范围查找,我想它既然索引都没用到,更不用谈去用索引排序了(不要去想为什么用name也是文件排序,name不是有序的吗,你要想都没用到索引,怎么用索引排序),只能用覆盖索引优化,因为where范围结果集大,回表次数多,所以用不到索引,优化如下(最好其它三条语句也用覆盖索引优化):

explain select id,name,age,address from member where name > 'gaorufeng' order by name;

优化总结:

  1. 务必要遵循最左前缀原则,不管是where、order by、group by
  2. 联合索引中,最左前缀字段在where中使用like、范围、or、in,后面都是无序的,因为排序都是文件排序,where条件中有时能用到索引,那是基于成本计算回表次数少才使用的索引,可以看到如果是范围查询基本上在大部分情况都用不到索引,只能把范围缩小,用覆盖索引优化
  3. 要使用索引字段排序,不然order by就会是文件排序
  4. order by和group by很类似,先排序后分组,同样遵循最左前缀原则,group by如果不需要排序可以使用order by null,最好不要用having,能在where中指定完条件那更好

2、filesort文件排序方式

explain select * from member where name = 'gaorufeng' order by address;
  1. 单路排序:首先找到name='gaorufeng'的主键id值,取出整行数据加载到sort_buffer中,继续找下一个符合条件的,一直这样循环;在sort_buffer中按照address字段进行排序
  2. 双路排序:首先找到name='gaorufeng'的主键id值,只取出id和address字段数据加载到sort_buffer中,继续找下一个符合条件的,一直这样循环;在sort_buffer中按照address字段进行排序,排序完之后再回表到原表中符合每个id的所有数据

3、索引设计原则

  • 代码先行,索引后上

        每次应该代码都写完了,才能确定什么业务场景下才能用到索引,或者更好的去建联合索引

  • 联合索引尽量覆盖条件

        where、group by、order by尽量包含在联合索引上,满足最左前缀原则,最好不要建单值索引,也不要随便去建索引,最好控制在两到三个就行了,因为mysql需要维护索引树

  • 不要在小基数上建索引

        比如只有字典类型的字段类型值比较少的情况,因为建了在索引树上的分布也是那几个,区分度不高

  • 长字符串采用前缀索引

        如果一个字段是varchar(255)的大字段,建索引的时候就可以只包含前20个字段就行了,类似与KEY index(name(20),age,address)

  • where与order by冲突时优先where

        想象一下也知道,先筛选结果,接着排序是不是也会快点

  • 基于慢sql查询做优化

        my.cnf要增加或修改参数slow_query_log=1和slow_query_log_file(慢sql文件存放路径)

show variables like 'long_query_time%';#查看多少秒会记录到慢查询日志里面

4、索引设计场景举例

假设一个商城的商品搜索场景,一般情况下有自动定位城市搜索,名称、商品编号、类型、价格

(`province`,`name`,`type`,`price`)

比如我们要搜索所有商品的价格在100到200之间的,然而,类型用户没有筛选,比如有电脑有苹果的、小米的、华为、华硕等等,这时候如果类型不多就这四种的情况下可以这样优化

select `province`,`name`,`type`,`price` from goods where province = '广州' and name like '笔记本电脑%' and type in ('苹果','小米','华为','华硕') and price >= 100 and price <= 200

假设这个时候根据用户的习惯,会选择商品的属性,比如游戏电脑,青春版、商业版、其它属性之内的,这个时候联合索引就应该是这样

(`province`,`name`,`type`,`style`,`price`)

如果这时候需要查询商品发布时间在最近7天的

(`province`,`name`,`type`,`style`,`price`,`publish_time`)

select `province`,`name`,`type`,`style`,`publish_time` from goods where province = '广州' and name like '笔记本电脑%' and type in ('苹果','小米','华为','华硕') and style = '青春版' and price >= 100 and price <= 200 and DATEDIFF(publish_time,NOW())=7

这样也不好,因为范围查询的后面基本上就是无序的,所以publish_time基本上用不到索引,而且还用了函数查询,就算把publish_time改成范围查询也是用不到,所以这时候就需要在程序中做处理了,新增一个字段is_recent_publish,把最近七天发布的商品的is_recent_publish改成1,这个时候联合索引的字段就应该是这样的

(`province`,`name`,`type`,`style`,is_recent_publish,`price`)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/657517.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode热题100】打卡第24天:单词搜索

文章目录 单词搜索⛅前言&#x1f512;题目&#x1f511;题解 单词搜索 ⛅前言 大家好&#xff0c;我是知识汲取者&#xff0c;欢迎来到我的LeetCode热题100刷题专栏&#xff01; 精选 100 道力扣&#xff08;LeetCode&#xff09;上最热门的题目&#xff0c;适合初识算法与数…

使用花生壳进行内网穿透实验SQLServer

使用的是体验版&#xff0c;进行实验足够了 &#xff08;1&#xff09;输入花生壳帐号密码登录花生壳管理平台&#xff0c;在【内网穿透】界面点击添加映射&#xff1b; &#xff08;2&#xff09;接着需要填写映射ERP服务器的相关内容&#xff1a;①应用类型&#xff1a;ERP系…

【论文系列解读】StableDiff总结

1. diffusion (0) 总结 可以参考此处&#xff1a;https://blog.csdn.net/weixin_40920183/article/details/130652651 https://zhuanlan.zhihu.com/p/599887666 总的来说&#xff0c;diffusion就是分为训练和采样两个阶段。 &#xff08;A&#xff09;训练阶段&#xff1a…

spring boot security快速使用示例

创建spring boot项目 生成脚手架 登录 https://start.spring.io/ 快速创建一个spring boot脚手架的demo&#xff1a; 配置依赖 因为本地依赖的原因&#xff0c;所以更换了spring boot版本为&#xff1a;2.6.11 <parent><groupId>org.springframework.boot<…

GC垃圾回收

GC垃圾回收 了解什么是垃圾回收掌握垃圾会回收的常见算法学习串行、并行、并发、G1垃圾收集器学习GC日志的可视化查看 1.什么是垃圾回收&#xff1f; 程序的运行必然需要申请内存资源&#xff0c;无效的对象资源如果不及时处理就会一直占有内存资源&#xff0c;最终将导致内…

设计模式(二十一):行为型之访问者模式

设计模式系列文章 设计模式(一)&#xff1a;创建型之单例模式 设计模式(二、三)&#xff1a;创建型之工厂方法和抽象工厂模式 设计模式(四)&#xff1a;创建型之原型模式 设计模式(五)&#xff1a;创建型之建造者模式 设计模式(六)&#xff1a;结构型之代理模式 设计模式…

Debian openssh-server 的安装

在之前安装系统的时候有一个安装 SSH 服务的&#xff0c;结果没点上&#xff0c;导致系统完成后&#xff0c;ssh无法连接上啊&#xff0c;于是要安装sshd 服务。使用命令&#xff1a;apt-get install openssh-server 结果就出现问题了&#xff1a; 网上搜索说是要更新源&#x…

004 maven 插件默认的

Maven – Guide to Configuring Plug-inshttps://maven.apache.org/guides/mini/guide-configuring-plugins.html 默认插件 参数 Apache Maven Compiler Plugin – compiler:compilehttps://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#forceJavacCom…

MATLAB读取OpenFOAM的二进制文件

OpenFOAM的文件格式 上面是OpenFOAM二进制文件的格式&#xff0c;我们可以看出&#xff0c;前面21行都是无关的说明文件&#xff0c;22开始时除了一个括号之外&#xff0c;其它的都是数据。 读取数据 读取数据的思路非常简单&#xff0c;忽略不需要的&#xff0c;读取需要的。…

第七十七天学习记录:高等数学:定积分应用(宋浩板书)

定积分是微积分的一种应用&#xff0c;通过定积分可以求出曲线下面的面积、弧长、质心、转动惯量等一系列物理量。以下是定积分的一些常见应用&#xff1a; 曲线下面的面积&#xff1a;定积分可以用于求曲线下面的面积。举个例子&#xff0c;如果想要求函数f(x) x^2在区间[0,1…

VFC芯片结构及其工作原理

&#xff08;二&#xff09; VFC芯片结构及其工作原理 1&#xff0e;VFC芯片 AD654的结构 AD654芯片是一个单片VFC变换芯片&#xff0c;中心频率为250kHZ。它是由阻抗变换器A、压控振荡器和一个驱动输出级回路构成&#xff0c;其内部结构见图1&#xff0d;15&#xff08;a入压…

VFC式数据采集系统

三、VFC式数据采集系统 &#xff08;一&#xff09;VFC型的A&#xff0f;D变换概述 一般来说在 A&#xff0f;D的变换过程中&#xff0c; CPU要使 S&#xff0f;H、 MPX、 A&#xff0f;D三个芯片之间控制协调好&#xff0c;因此接口电路复杂。而且ADC芯片结构较复杂&#xff0…

车载软件架构 —— 闲聊几句AUTOSAR OS(五)

我是穿拖鞋的汉子,魔都中坚持长期主义的工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 没有人关注你。也无需有人关注你。你必须承认自己的价值,你不能站在他人的角度来反对自己。人生在世,最怕的就是把别人的眼光当成自己生活的唯一标准。到最…

Nature揭示--迷幻药物如何实现其强大的健康益处

迷幻药物MDMA&#xff08;也称为摇头丸&#xff09;的结晶&#xff0c;可以恢复小鼠从环境中学习特定方面的能力。图片来源&#xff1a; Police Scotland/Contraband Collection/Alamy 迷幻药物是一类能够引起意识状态改变的药物&#xff0c;被广泛应用于精神和医疗领域。尽管迷…

【简单便捷】解决Ubuntu内存不足问题:Ubuntu16.0.4 进行内存扩容

文章目录 电脑环境前言一、总述二、先在标题&#xff1a;虚拟机-->设置上进行扩容三、扩容之后 打开终端 执行 sudo apt install gparted四、执行 sudo gparted五、扩容成功六、重启测试 可以看到大概率成功了。 电脑环境 Windows 11 专业版系统 前言 在开发初期&#xf…

232 · 短网址

链接&#xff1a;LintCode 炼码 题解&#xff1a; class TinyUrl { public:/** param url: a long url* return: a short url starts with http://tiny.url/*/string longToShort(string &url) {// write your code herestd::string shorturl generate_shorturl(url);whi…

为CentOs配置静态IP

目录 第一步&#xff1a;查看物理机IP 第二步&#xff1a;虚拟机网络设置 点击虚拟机->编辑虚拟机设置 第三步&#xff1a;CentOS网络配置文件 第四步&#xff1a;重启网络 第五步&#xff1a;测试网络 为什么要设置静态IP 在安装好CentOS虚拟机以后&#xff0c;一般我…

代码随想录算法训练营第三十九天| 62.不同路径 、63. 不同路径 II

不同路径 题目链接&#xff1a;力扣 题外话&#xff1a;这题拿到的时候就发现其实是小学三年级的奥数题&#xff0c;甚至寒假看我妹做过【笑哭&#x1f602;】 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 dp[i][j] &#xff1a;表示从&#xff08;0,0&…

nvm控制nodejs版本

1.关系如图 2. 环境配置 3.报错解决 路径导致的nvm安装nodejs失败&#xff1f; The system cannot find the path specified. Could not download node.js v16.19.1 64-bit executable. 解决&#xff1a;nvm安装路径D:\Program Files\nvm&#xff0c;nvm管理的nodejs路径D:\Pro…

在Qgis中使用QMetaTiles插件进行XYZ瓦片离线下载方法

目录 前言 一、Qgis插件库 1、插件库简介 2、QMetaTiles介绍 二、QMetaTiles插件安装 1、在线安装 2、离线安装 三、瓦片下载 1、打开QmeaTiles插件 2、Leaflet加载下载的瓦片 总结 前言 电子地图是地图类应用的基石&#xff0c;作为整个系统的基础。其它的图层要素都构…