sql语句分析是否走索引_SQL语句无法走索引的一些情况分析及语句改写思路
因为优化器还不够强大,还有很多限制,或者因为一些逻辑原因,分析认为SQL要走索引比较好,但是事实却无法正确利用索引。这时候,除了给ORACLE需要的统计信息之外,写的SQL必须要能够给优化器足够多的额外有效信息,让优化器能够选择更好的执行计划。要让给优化器正确使用上需要的索引,要考虑两点:1).如何避免优化器的限制 2).根据业务数据特点改写SQL语句说明:这里说的走不了索引,是指走不了正常的RANGE SCAN,非(FAST) FULL INDEX SCAN。1.谓词使用不等于(<>,!=),目前的优化器一般认为不等于的选择性不好,会找到很多行,所以用不上索引,就算强制索引,也是扫描全部的索引,走不了RANGE SCAN如果事实走索引定位较好,那么解决方法: 1)如果不等条件之外的值不多,而且是确认的,可以改为等值或IN查询,比如status状态字段一般值类别很少 2)如果不等条件之外的值很多,可以改为> OR
DROP TABLE t;CREATE TABLE t AS SELECT LEVEL ID,rpad('x',10,'x') padding,CAST('JACK' AS VARCHAR2(100)) NAMEFROM dualCONNECT BY LEVEL<100000;--构造3行较少的值INSERT INTO t VALUES(100000,'y','DINGJUN1');INSERT INTO t VALUES(100001,'y','DINGJUN2');INSERT INTO t VALUES(100002,'y','DINGJUN3');COMMIT;ALTER TABLE t MODIFY NAME NOT NULL;--创建索引CREATE INDEX idx_t ON t(NAME);BEGIN dbms_stats.gather_table_stats(ownname => USER,tabname => 'T',estimate_percent => 100,method_opt => 'for columns name size 10',cascade => TRUE);END;/
<>无法利用索引:
dingjun123@ORADB> SELECT * FROM t 2 WHERE t.name<>'JACK';3 rows selected.Elapsed: 00:00:00.01Execution Plan----------------------------------------------------------Plan hash value: 1601196873--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 4 | 88 | 107 (2)| 00:00:02 ||* 1 | TABLE ACCESS FULL| T | 4 | 88 | 107 (2)| 00:00:02 |--------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("T"."NAME"<>'JACK')
将<>改写为OR连接后,能够正确使用索引,走OR扩展:
dingjun123@ORADB> SELECT * FROM t 2 WHERE t.NAME>'JACK' OR t.NAME 'JACK') 5 - access("T"."NAME"'JACK'))
如果业务允许,改为写下列语句也是走索引的,不再演示。 SELECT * FROM tWHERE t.NAME IN ('DINGJUN1','DINGJUN2','DINGJUN3');NOT IN,NOT EXISTS与<>类似,也是走不了索引的(注意,这里说走不了索引,只针对于不等连接谓词,不包括其他谓词)演示NOT IN:
DROP TABLE t1;CREATE TABLE t1 AS SELECT 1 ID,'JACK' NAME FROM dual;ALTER TABLE t1 MODIFY NAME NOT NULL; BEGIN dbms_stats.gather_table_stats(ownname => USER,tabname => 'T1',estimate_percent => 100);END;/
NOT IN也不能使用索引,强制使用只能扫描全部索引:
dingjun123@ORADB> SELECT * FROM t 2 WHERE t.NAME NOT IN(SELECT t1.NAME FROM t1);Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 4253491563-----------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-----------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 100K| 2636K| 110 (2)| 00:00:02 ||* 1 | HASH JOIN RIGHT ANTI| | 100K| 2636K| 110 (2)| 00:00:02 || 2 | TABLE ACCESS FULL | T1 | 1 | 5 | 3 (0)| 00:00:01 || 3 | TABLE ACCESS FULL | T | 100K| 2148K| 106 (1)| 00:00:02 |-----------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - access("T"."NAME"="T1"."NAME")dingjun123@ORADB> SELECT/*+index(t idx_t)*/ * FROM t 2 WHERE t.NAME NOT IN(SELECT t1.NAME FROM t1);Elapsed: 00:00:00.03Execution Plan----------------------------------------------------------Plan hash value: 1707532828--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 100K| 2636K| 591 (1)| 00:00:08 || 1 | MERGE JOIN ANTI | | 100K| 2636K| 591 (1)| 00:00:08 || 2 | TABLE ACCESS BY INDEX ROWID| T | 100K| 2148K| 587 (1)| 00:00:08 || 3 | INDEX FULL SCAN | IDX_T | 100K| | 225 (1)| 00:00:03 ||* 4 | SORT UNIQUE | | 1 | 5 | 4 (25)| 00:00:01 || 5 | TABLE ACCESS FULL | T1 | 1 | 5 | 3 (0)| 00:00:01 |--------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 4 - access("T"."NAME"="T1"."NAME") filter("T"."NAME"="T1"."NAME")
NOT EXISTS与NOT IN类似(注意,NOT IN已经处理过NULL的影响) SELECT * FROM t WHERE NOT EXISTS(SELECT 1 FROM t1 WHERE t.NAME=t1.NAME);2.由于B*Tree索引不存储全为NULL的行,造成无法走索引的情况解决方法: 1)视业务要求是否可以不统计NULL的 加条件where xxx IS NOT NULL, COUNT(列).....等等过滤NULL的语句 2)复合列索引 3)函数索引详细可以参考这个帖子里的内容。3.LIKE前通配查询询,LIKE全通配查询走不了索引解决方法:1)是否可以根据业务需求把前通配去掉
dingjun123@ORADB> SELECT * FROM t WHERE t.NAME LIKE '%DINGJUN%';Elapsed: 00:00:00.04Execution Plan----------------------------------------------------------Plan hash value: 1601196873--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 5000 | 107K| 107 (2)| 00:00:02 ||* 1 | TABLE ACCESS FULL| T | 5000 | 107K| 107 (2)| 00:00:02 |--------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("T"."NAME" LIKE '%DINGJUN%')--改为后通配,走索引dingjun123@ORADB> SELECT * FROM t WHERE t.NAME LIKE 'DINGJUN%';Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 1594971208-------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 3 | 66 | 3 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T | 3 | 66 | 3 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | IDX_T | 3 | | 2 (0)| 00:00:01 |-------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("T"."NAME" LIKE 'DINGJUN%') filter("T"."NAME" LIKE 'DINGJUN%')
2) 是否和此LIKE一样的前通配或全通配的SQL有很多,此谓词的LIKE变化不大,如果是,考虑建立函数索引,否则对于全通配问题最好办法就是全文索引
dingjun123@ORADB> CREATE INDEX idx1_t ON t (instr(NAME,'DINGJUN'));Index created.Elapsed: 00:00:00.16dingjun123@ORADB> SELECT * FROM t WHERE instr(t.NAME,'DINGJUN')>0;Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 2071967826--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 5000 | 102K| 7 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T | 5000 | 102K| 7 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | IDX1_T | 900 | | 3 (0)| 00:00:01 |--------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access(INSTR("NAME",'DINGJUN')>0)
3)如果只是前通配,可以使用reverse函数索引(不是翻转键索引) SELECT * FROM t WHERE t.NAME LIKE '%DINGJUN1'; CREATE INDEX idx2_t ON t(REVERSE(NAME)); 语句要改写,使用reverse函数谓词,并且查找值倒查:
dingjun123@ORADB> SELECT * FROM t WHEREREVERSE(t.NAME) LIKE '1NUJGNID%';Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 3787301248--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 5000 | 102K| 8 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T | 5000 | 102K| 8 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | IDX2_T | 900 | | 4 (0)| 00:00:01 |--------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access(REVERSE("NAME") LIKE '1NUJGNID%') filter(REVERSE("NAME") LIKE '1NUJGNID%')
注意:如果查找的是中文,得注意,不可直接写REVERSE(t.NAME) LIKE '1NUJGNID%',因为REVERSE内部会按字节翻转,中文的写法可以用REVERSE转换,比如SELECT * FROM t WHERE REVERSE(t.name) LIKE REVERSE('数据')||'%';否则查询出的数据不对。4.对索引列使用了函数,数学运算,其他表达式等解决方法:去掉对索引列的相关运算,保持索引列纯净。优化器目前对一些数学运算,还无法做很好的消除动作,所以对于索引列应该尽量保持纯净,否则可能无法用上正确的索引
dingjun123@ORADB> CREATE INDEX idx3_t ON t(ID);Index created.Elapsed: 00:00:00.13dingjun123@ORADB> ALTER TABLE T MODIFY ID NOT NULL;Table altered.Elapsed: 00:00:00.10dingjun123@ORADB> SELECT * FROM t WHERE ID+0=1;Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 1601196873--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1000 | 21000 | 107 (2)| 00:00:02 ||* 1 | TABLE ACCESS FULL| T | 1000 | 21000 | 107 (2)| 00:00:02 |--------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("ID"+0=1)dingjun123@ORADB> SELECT * FROM t WHERE ID=1;Elapsed: 00:00:00.01Execution Plan----------------------------------------------------------Plan hash value: 2351669764--------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1000 | 21000 | 3 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T | 1000 | 21000 | 3 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | IDX3_T | 400 | | 1 (0)| 00:00:01 |--------------------------------------------------------------------------------------Predicate Information (identified by operation id):---------------------------------------------------2 - access("ID"=1)
举例只是举简单的数学运算,可能运算还和其他列运算,比如where ID+ext_col...5.ORACLE使用了隐式类型转换,导致索引无法使用 解决方法:必须避免隐式类型转换,全部要求显式类型转换(非索引列),且避免对索引列进行类型转换(有函数索引除外)如果类型不一致,不管是否发生自动类型转换,谓词的右值应该显式转换为与索引列保持一致(对于非索引列的运算也应该如此)。
dingjun123@ORADB> DROP TABLE t1;Table dropped.Elapsed: 00:00:00.03dingjun123@ORADB> CREATE TABLE t1(x VARCHAR2(100));Table created.Elapsed: 00:00:00.04dingjun123@ORADB> CREATE INDEX idx_t1 ON t1(x);Index created.Elapsed: 00:00:00.04dingjun123@ORADB> SELECT * FROM t1 WHERE x = 1;Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 3617692013--------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |--------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 52 | 2 (0)| 00:00:01 ||* 1 | TABLE ACCESS FULL| T1 | 1 | 52 | 2 (0)| 00:00:01 |--------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter(TO_NUMBER("X")=1)dingjun123@ORADB> SELECT * FROM t1 WHERE x = '1';Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 1369807930---------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1 | 52 | 1 (0)| 00:00:01 ||* 1 | INDEX RANGE SCAN| IDX_T1 | 1 | 52 | 1 (0)| 00:00:01 |---------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - access("X"='1')
发生类型转换,可以通过执行计划中的谓词信息获知。通过分析发现,X因为是VARCHAR2,优先级比数值类型低,遇到数值类型,会TO_NUMBER,所以索引失效,通过传入与索引列类型一致的字符串后,解决。6.对于其他不走索引的,尽量通过业务的逻辑特点改写语句,可能正确利用索引例如一个典型的例子:
DROP TABLE t_objects;CREATE TABLE t_objectsASSELECT * FROM dba_objects;CREATE INDEX idx_t_objects ON t_objects(last_ddl_time,created);BEGIN dbms_stats.gather_table_stats(ownname => USER,tabname => 't_objects',estimate_percent => 100,cascade => TRUE);END;/
需求:查找创建时间是2013年的,并且最后ddl时间比创建时间大1天以上。
dingjun123@ORADB> SELECT * FROM 2 t_objects t 3 WHERE t.last_ddl_time-t.created>1 4 AND t.created>=DATE'2013-1-1';Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 3629755566-------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 1171 | 110K| 300 (1)| 00:00:04 ||* 1 | TABLE ACCESS FULL| T_OBJECTS | 1171 | 110K| 300 (1)| 00:00:04 |-------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("T"."CREATED">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."LAST_DDL_TIME"-"T"."CREATED">1)
这个索引是组合索引,上面的语句对前导列进行了运行,也不符合走index skip scan的条件,所以,走FULL TABLE SCAN。那么是否可以通过逻辑改写走索引呢,通过第4点得知,要保持索引列清净,将create_date移到右边,语句如下:
dingjun123@ORADB> SELECT * FROM 2 t_objects t 3 WHERE t.last_ddl_time>=(t.created+1) 4 AND t.created>=DATE'2013-1-1';Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 3629755566-------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |-------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 403 | 39091 | 301 (1)| 00:00:04 ||* 1 | TABLE ACCESS FULL| T_OBJECTS | 403 | 39091 | 301 (1)| 00:00:04 |-------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 1 - filter("T"."CREATED">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."LAST_DDL_TIME">=INTERNAL_FUNCTION("T" ."CREATED")+1)
通过改写后发现,还是没有走索引,因为ORACLE认为前导列右边的created不固定,无法从指定索引处查找。通过这个分析得知,ORACLE谓词传递有一定限制,create_date+1无法做谓词传递给last_ddl_time,改写:
dingjun123@ORADB> SELECT * FROM 2 t_objects t 3 WHERE t.last_ddl_time>=(t.created) 4 AND t.last_ddl_time>=(t.created+1) 5 AND t.created>=DATE'2013-1-1';Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 641904483---------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 2 | 194 | 11 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T_OBJECTS | 2 | 194 | 11 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | IDX_T_OBJECTS | 6 | | 10 (0)| 00:00:01 |---------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("T"."LAST_DDL_TIME">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."CREATED">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."LAST_DDL_TIME" IS NOT NULL) filter("T"."CREATED">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."LAST_DDL_TIME">="T"."CREATED" AND "T"."LAST_DDL_TIME">=INTERNAL_FUNCTION("T"."CREATED")+1)
上面的oracle知道谓词传递给last_ddl_time了,T"."LAST_DDL_TIME">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss'),也可以手动谓词传递,last_ddl_time肯定大于等于DATE'2013-1-2':
dingjun123@ORADB> SELECT * FROM 2 t_objects t 3 WHERE t.last_ddl_time>=DATE'2013-1-2' 4 AND t.last_ddl_time>=(t.created+1) 5 AND t.created>=DATE'2013-1-1';Elapsed: 00:00:00.00Execution Plan----------------------------------------------------------Plan hash value: 641904483---------------------------------------------------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |---------------------------------------------------------------------------------------------| 0 | SELECT STATEMENT | | 13 | 1261 | 11 (0)| 00:00:01 || 1 | TABLE ACCESS BY INDEX ROWID| T_OBJECTS | 13 | 1261 | 11 (0)| 00:00:01 ||* 2 | INDEX RANGE SCAN | IDX_T_OBJECTS | 13 | | 10 (0)| 00:00:01 |---------------------------------------------------------------------------------------------Predicate Information (identified by operation id):--------------------------------------------------- 2 - access("T"."LAST_DDL_TIME">=TO_DATE(' 2013-01-02 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."CREATED">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."LAST_DDL_TIME" IS NOT NULL) filter("T"."CREATED">=TO_DATE(' 2013-01-01 00:00:00', 'syyyy-mm-dd hh24:mi:ss') AND "T"."LAST_DDL_TIME">=INTERNAL_FUNCTION("T"."CREATED")+1)
当然,对于两个都是范围的查询,这里只能通过一个列来轮询索引,先做access,再做filter。SQL语句的逻辑改写很重要,往往通过逻辑改写就能改变SQL的执行计划,从不好的计划到好的计划,比如semi join,anti join与or,往往走FILTER导致执行计划较差,这时候就需要通过逻辑等价改写,逻辑等价改写往往需要掌握一些集合的知识,比如NOT (A AND B)===NOT A OR NOT B,NOT (A OR B)===NOT A AND NOT B等。
sql语句分析是否走索引_SQL语句无法走索引的一些情况分析及语句改写思路相关推荐
- sql聚集索引和非聚集索引_SQL Server中非聚集索引概述
sql聚集索引和非聚集索引 This article gives an introduction of the non-clustered index in SQL Server using exam ...
- mysql嵌套子查询索引_SQL 子查询,索引优化
场景 索引优化 单列索引 多列索引 索引覆盖 排序 场景 我用的数据库是mysql5.6,下面简单的介绍下场景 课程表 create table Course( c_id int PRIMARY KE ...
- 中国拖拉机市场情况分析与发展趋势预测分析报告2022-2028年版
中国拖拉机市场情况分析与发展趋势预测分析报告2022-2028年版 [报告目录]: 第一章 拖拉机相关概述 1.1 拖拉机的基本概念 1.1.1 拖拉机介绍 1.1.2 拖拉机的分类 1. ...
- sql语句创建索引_SQL创建索引语句示例说明
sql语句创建索引 This statement is used to create an "index" on a column in an existing table. 该语 ...
- SQL语句(数据库、基本表、视图、索引)
SQL语句 一.数据库 1.创建数据库(CREATE) /*语法格式*/ CREATE DATABASE 数据库名称 ON (NAME=数据文件逻辑名称,FILENAME='PATH',SIZE=数据 ...
- groovy怎样从sql语句中截取表名_sql注入mysql篇
SQL注入 __0x01 ♛Sql注入原理 Sql注入顾名思义是没有对用户输入的参数进行过滤导致测试者可以将一段非正常语句插入到查询语句中,由web应用带入到数据库中执行,从而读取数据库中的数据. _ ...
- groupby索引有效吗_SQL IN 一定走索引吗?
摘要 IN 一定走索引吗?那当然了,不走索引还能全部扫描吗?好像之前有看到过什么Exist,IN走不走索引的讨论.但是好像看的太久了,又忘记了.哈哈,如果你也忘记了MySQL中IN是如何查询的,就来复 ...
- sql组合索引和独立索引_SQL索引概述和策略
sql组合索引和独立索引 A SQL index is used to retrieve data from a database very fast. Indexing a table or vie ...
- sql分区表上创建索引_SQL Server中分区表和索引的选项
sql分区表上创建索引 介绍 (Introduction) I work for a large, multinational financial institution. Like most com ...
最新文章
- Linux 多线程同步机制:互斥量、信号量、条件变量
- [Asp.net mvc]OutputCacheAttribute
- python【力扣LeetCode算法题库】206-反转链表
- clear java_Java ConcurrentLinkedDeque clear()用法及代码示例
- led显示屏背景墙设计_室内LED 显示屏室内安装设计
- dom复制cloneNode节点与插入节点appendChild()
- 最大熵模型:读书笔记
- 在linux中安装软件会出的问题,linux中安装程序出现的问题
- 常见DDoS技术方法和对应防御措施
- 计算机课程教改论文,高职计算机教改的课程设计研究论文
- 2d游戏地图编辑器_C语言实现大型2D格斗游戏,1.8万行代码!
- SaaS架构设计之如何转化成SaaS多租户模式
- SpringMVC学习(七)使用JSON传递数据、jackson和fastjson的使用、处理JSON传输的乱码问题
- 沙盘模拟软件_重大消息:企业经营沙盘招新啦
- WIN7显示桌面图标设置到左下角
- 数据治理:携程度假的数据治理实践
- 解决jellyfin媒体库标题乱码
- yar php使用,PHP yar的使用简介
- dismiss ios pop效果_iOS ~ ViewController的Push,Pop和Present,Dismiss转场动画
- 养生之道---六字气决
热门文章
- [linux 命令笔记] kill
- MFC开发IM-第三篇、资源视图--显示在另一个编辑器中打开
- 小米集团2021年Q4净利润45亿元 同比增长39.6%
- 2199元起!荣耀60 SE真机上手图公布:相机模组造型眼熟
- 相互宝正式宣布将于2022年1月28日关停
- 京东健康CEO辛利军:感谢刘强东的战略格局和超前眼光
- QQ正式上线QID功能 用户可自定义专属身份卡
- 开机先看广告!智能电视这流氓操作被整治,这家厂商败诉
- iPhone 12系列全新渲染图曝光:4个“杯型” 起售价可能不到5k
- 蔚来ES8正式交付售价46.8万元起 与Model系相比扛打吗?