• 关于 数据库order by 数字 的搜索结果

问题

RANGE_HASH如何使用

猫饭先生 2019-12-01 21:20:15 861 浏览量 回答数 0

问题

如何选择拆分键

猫饭先生 2019-12-01 21:20:53 1364 浏览量 回答数 0

问题

OceanBase支持的函数概述

云栖大讲堂 2019-12-01 21:28:37 948 浏览量 回答数 0

海外云虚拟主机包年25元/月起

海外独享虚拟主机全面上线,助力构建海外网站,提升公司国际形象;全球有效覆盖,超高性价比;建站入门首选,助力出口,适合跨境贸易企业。

回答

胜哥 作者出的题目建表的sql能提供下吗? 35题 select sum(count) as num,id from ( select count(*) count,requester_id as id from request_accepted GROUP BY requester_id UNION select count(*) count ,accepter_id as id from request_accepted GROUP BY accepter_id )t GROUP BY id ORDER BY num desc limit 1 33题 1.初始化: CREATE TABLE `Orders` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `shop_id` varchar(10) COLLATE utf8mb4_bin DEFAULT NULL, `pay_date` datetime DEFAULT NULL, `pay_no` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin INSERT INTO `Orders`(`id`, `shop_id`, `pay_date`, `pay_no`) VALUES (1, '1001', '2020-01-11 16:43:25', 5); INSERT INTO `Orders`(`id`, `shop_id`, `pay_date`, `pay_no`) VALUES (2, '1001', '2020-01-10 16:43:57', 3); INSERT INTO `Orders`(`id`, `shop_id`, `pay_date`, `pay_no`) VALUES (3, '1002', '2020-01-17 16:44:09', 4); INSERT INTO `Orders`(`id`, `shop_id`, `pay_date`, `pay_no`) VALUES (4, '1002', '2020-01-11 16:44:24', 2); INSERT INTO `Orders`(`id`, `shop_id`, `pay_date`, `pay_no`) VALUES (5, '1002', '2020-01-11 16:44:24', 1); INSERT INTO `Orders`(`id`, `shop_id`, `pay_date`, `pay_no`) VALUES (6, '1002', '2020-01-12 16:44:24', 0); 2.SQL 方法1:GROUP_CONCAT实现(数据库版本[5.7.16]) select * from Orders where id in ( select SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY pay_date,pay_no),',',1) from Orders GROUP BY shop_id ) 方法2:子查询实现(数据库版本[5.6.16]) select t.* from ( select * from Orders ORDER BY pay_date ,pay_no )t GROUP BY t.shop_id; 方法2有可能是不行的,不知道是数据库版本问题还是哪里设置没有 3.注意: GROUP_CONCAT有长度限制,记录过多需要注意设置以下配置 SET @@global.group_concat_max_len=数字

1074800250556052 2020-01-13 10:04:51 0 浏览量 回答数 0

回答

在任何MySQL语句中添加PHP变量的规则很简单: 任何表示SQL数据文字的变量(或简单地说-SQL字符串或数字)都必须通过准备好的语句添加。没有例外。 任何其他查询部分(例如SQL关键字,表或字段名或运算符)都必须通过白名单进行过滤。 因此,由于您的示例仅涉及数据文字,因此必须通过占位符(也称为参数)添加所有变量。为此: 在您的SQL语句中,将所有变量替换为占位符 准备结果查询 将变量绑定到占位符 执行查询 以下是使用所有流行的PHP数据库驱动程序的方法: 使用mysql_query添加数据文字 这样的驱动程序不存在。 使用添加数据文字 mysqli $type = 'testing'; $reporter = "John O'Hara"; $query = "INSERT INTO contents (type, reporter, description) VALUES(?, ?, 'whatever')"; $stmt = $mysqli->prepare($query); $stmt->bind_param("ss", $type, $reporter); $stmt->execute(); 代码有点复杂,但是所有这些运算符的详细说明都可以在我的文章“ 如何使用Mysqli运行INSERT查询”中找到,并且可以大大简化该过程。 使用PDO添加数据文字 $type = 'testing'; $reporter = "John O'Hara"; $query = "INSERT INTO contents (type, reporter, description) VALUES(?, ?, 'whatever')"; $stmt = $pdo->prepare($query); $stmt->execute([$type, $reporter]); 在PDO中,我们可以将绑定和执行部分组合在一起,这非常方便。PDO还支持命名占位符,有些占位符非常方便。 添加关键字或标识符 但是有时我们添加了一个代表查询的另一部分的变量,例如关键字或标识符(数据库,表或字段名)。在这种情况下,必须对照在脚本中明确编写的值列表检查变量。这在我的另一篇文章《基于用户的选择在ORDER BY子句中添加字段名称》中进行了解释: 不幸的是,PDO没有标识符(表和字段名)的占位符,因此开发人员必须手动过滤掉它们。这种过滤器通常称为“白名单”(我们只列出允许的值),而不是“黑名单”,其中列出不允许的值。 因此,我们必须在PHP代码中明确列出所有可能的变体,然后从中进行选择。 这是一个例子: $orderby = $_GET['orderby'] ?: "name"; // set the default value $allowed = ["name","price","qty"]; // the white list of allowed field names $key = array_search($orderby, $allowed, true); // see if we have such a name if ($key === false) { throw new InvalidArgumentException("Invalid field name"); } 方向应使用完全相同的方法, $direction = $_GET['direction'] ?: "ASC"; $allowed = ["ASC","DESC"]; $key = array_search($direction, $allowed, true); if ($key === false) { throw new InvalidArgumentException("Invalid ORDER BY direction"); } 这样的代码之后,$direction和$orderby变量都可以安全地放入SQL查询中,因为它们等于允许的变体之一,否则将引发错误。 关于标识符的最后一件事,还必须根据特定的数据库语法设置它们的格式。对于MySQL,它应该是backtick标识符周围的字符。因此,示例中最终订单的查询字符串为 $query = "SELECT * FROM table ORDER BY $orderby $direction";来源:stack overflow

保持可爱mmm 2020-05-08 10:47:16 0 浏览量 回答数 0

回答

索引,索引!!!为经常查询的字段建索引!! 但也不能过多地建索引。insert和delete等改变表记录的操作会导致索引重排,增加数据库负担。优化目标1.减少 IO 次数 IO永远是数据库最容易瓶颈的地方,这是由数据库的职责所决定的,大部分数据库操作中超过90%的时间都是 IO 操作所占用的,减少 IO 次数是 SQL 优化中需要第一优先考虑,当然,也是收效最明显的优化手段。2.降低 CPU 计算 除了 IO 瓶颈之外,SQL优化中需要考虑的就是 CPU 运算量的优化了。order by, group by,distinct … 都是消耗 CPU 的大户(这些操作基本上都是 CPU 处理内存中的数据比较运算)。当我们的 IO 优化做到一定阶段之后,降低 CPU 计算也就成为了我们 SQL 优化的重要目标优化方法改变 SQL 执行计划 明确了优化目标之后,我们需要确定达到我们目标的方法。对于 SQL 语句来说,达到上述2个目标的方法其实只有一个,那就是改变 SQL 的执行计划,让他尽量“少走弯路”,尽量通过各种“捷径”来找到我们需要的数据,以达到 “减少 IO 次数” 和 “降低 CPU 计算” 的目标分析复杂的SQL语句explain 例如: mysql> explain select from (select from ( select * from t3 where id=3952602) a) b; id select_type table type possible_keys key key_len ref rows Extra 1 PRIMARY system NULL NULL NULL NULL 1 2 DERIVED system NULL NULL NULL NULL 1 3 DERIVED t3 const PRIMARY,idx_t3_id PRIMARY 4 1 很显然这条SQL是从里向外的执行,就是从id=3 向上执行.show show tables或show tables from database_name; // 显示当前数据库中所有表的名称 show databases; // 显示mysql中所有数据库的名称 show columns from table_name from database_name; 或MySQL show columns from database_name.table_name; // 显示表中列名称 show grants for user_name@localhost; // 显示一个用户的权限,显示结果类似于grant 命令 show index from table_name; // 显示表的索引 show status; // 显示一些系统特定资源的信息,例如,正在运行的线程数量 show variables; // 显示系统变量的名称和值show processlist; // 显示系统中正在运行的所有进程,也就是当前正在执行的查询。 show table status; // 显示当前使用或者指定的database中的每个表的信息。信息包括表类型和表的最新更新时间 show privileges; // 显示服务器所支持的不同权限 show create database database_name; // 显示create database 语句是否能够创建指定的数据库 show create table table_name; // 显示create database 语句是否能够创建指定的数据库 show engies; // 显示安装以后可用的存储引擎和默认引擎。 show innodb status; // 显示innoDB存储引擎的状态 show logs; // 显示BDB存储引擎的日志 show warnings; // 显示最后一个执行的语句所产生的错误、警告和通知 show errors; // 只显示最后一个执行语句所产生的错误关于enum 存在争议。 对于取值有限且固定的字段,推荐使用enum而非varchar。但是!!其他数据库可能不支持,导致了难于迁移的问题。开启缓存查询 对于完全相同的sql,使用已经存在的执行计划,从而跳过解析和生成执行计划的过程。 应用场景:有一个不经常变更的表,且服务器收到该表的大量相同查询。对于频繁更新的表,查询缓存是不适合的 Mysql 判断是否命中缓存的办法很简单,首先会将要缓存的结果放在引用表中,然后使用查询语句,数据库名称,客户端协议的版本等因素算出一个hash值,这个hash值与引用表中的结果相关联。如果在执行查询时,根据一些相关的条件算出的hash值能与引用表中的数据相关联,则表示查询命中 查询必须是完全相同的(逐字节相同)才能够被认为是相同的。另外,同样的查询字符串由于其它原因可能认为是不同的。使用不同的数据库、不同的协议版本或者不同 默认字符集的查询被认为是不同的查询并且分别进行缓存。 下面sql查询缓存认为是不同的: SELECT * FROM tbl_name Select * from tbl_name 缓存机制失效的场景 如果查询语句中包含一些不确定因素时(例如包含 函数Current()),该查询不会被缓存,不确定因素主要包含以下情况 · 引用了一些返回值不确定的函数 · 引用自定义函数(UDFs)。 · 引用自定义变量。 · 引用mysql系统数据库中的表。 · 下面方式中的任何一种: SELECT ...IN SHARE MODE SELECT ...FOR UPDATE SELECT ...INTO OUTFILE ... SELECT ...INTO DUMPFILE ... SELECT * FROM ...WHERE autoincrement_col IS NULL · 使用TEMPORARY表。 · 不使用任何表。 · 用户有某个表的列级别权限。额外的消耗 如果使用查询缓存,在进行读写操作时会带来额外的资源消耗,消耗主要体现在以下几个方面 · 查询的时候会检查是否命中缓存,这个消耗相对较小 · 如果没有命中查询缓存,MYSQL会判断该查询是否可以被缓存,而且系统中还没有对应的缓存,则会将其结果写入查询缓存 · 如果一个表被更改了,那么使用那个表的所有缓冲查询将不再有效,并且从缓冲区中移出。这包括那些映射到改变了的表的使用MERGE表的查询。一个表可以被许多类型的语句更改,例如INSERT、UPDATE、DELETE、TRUNCATE、ALTER TABLE、DROP TABLE或DROP DATABASE。 对于InnoDB而言,事物的一些特性还会限制查询缓存的使用。当在事物A中修改了B表时,因为在事物提交之前,对B表的修改对其他的事物而言是不可见的。为了保证缓存结果的正确性,InnoDB采取的措施让所有涉及到该B表的查询在事物A提交之前是不可缓存的。如果A事物长时间运行,会严重影响查询缓存的命中率 查询缓存的空间不要设置的太大。 因为查询缓存是靠一个全局锁操作保护的,如果查询缓存配置的内存比较大且里面存放了大量的查询结果,当查询缓存失效的时候,会长时间的持有这个全局锁。因为查询缓存的命中检测操作以及缓存失效检测也都依赖这个全局锁,所以可能会导致系统僵死的情况静态表速度更快定长类型和变长类型 CHAR(M)定义的列的长度为固定的,M取值可以为0~255之间,当保存CHAR值时,在它们的右边填充空格以达到指定的长度。当检索到CHAR值时,尾部的空格被删除掉。在存储或检索过程中不进行大小写转换。CHAR存储定长数据很方便,CHAR字段上的索引效率级高,比如定义char(10),那么不论你存储的数据是否达到了10个字节,都要占去10个字节的空间,不足的自动用空格填充。 VARCHAR(M)定义的列的长度为可变长字符串,M取值可以为0~65535之间,(VARCHAR的最大有效长度由最大行大小和使用的字符集确定。整体最大长度是65,532字节)。VARCHAR值保存时只保存需要的字符数,另加一个字节来记录长度(如果列声明的长度超过255,则使用两个字节)。VARCHAR值保存时不进行填充。当值保存和检索时尾部的空格仍保留,符合标准SQL。varchar存储变长数据,但存储效率没有CHAR高。 如果一个字段可能的值是不固定长度的,我们只知道它不可能超过10个字符,把它定义为 VARCHAR(10)是最合算的。VARCHAR类型的实际长度是它的值的实际长度+1。空间上考虑,用varchar合适;从效率上考虑,用char合适,关键是根据实际情况找到权衡点。VARCHAR和TEXT、BlOB类型 VARCHAR,BLOB和TEXT类型是变长类型,对于其存储需求取决于列值的实际长度(在前面的表格中用L表示),而不是取决于类型的最大可能尺寸。 BLOB和TEXT类型需要1,2,3或4个字节来记录列值的长度,这取决于类型的最大可能长度。VARCHAR需要定义大小,有65535字节的最大限制;TEXT则不需要。如果你把一个超过列类型最大长度的值赋给一个BLOB或TEXT列,值被截断以适合它。 一个BLOB是一个能保存可变数量的数据的二进制的大对象。4个BLOB类型TINYBLOB、BLOB、MEDIUMBLOB和LONGBLOB仅仅在他们能保存值的最大长度方面有所不同。 BLOB 可以储存图片,TEXT不行,TEXT只能储存纯文本文件。 在BLOB和TEXT类型之间的唯一差别是对BLOB值的排序和比较以大小写敏感方式执行,而对TEXT值是大小写不敏感的。换句话说,一个TEXT是一个大小写不敏感的BLOB。 效率来说基本是char>varchar>text,但是如果使用的是Innodb引擎的话,推荐使用varchar代替char char和varchar可以有默认值,text不能指定默认值静态表和动态表 静态表字段长度固定,自动填充,读写速度很快,便于缓存和修复,但比较占硬盘,动态表是字段长度不固定,节省硬盘,但更复杂,容易产生碎片,速度慢,出问题后不容易重建。当只需要一条数据的时候,使用limit 1 表记录中的一行尽量不要超过一个IO单元 区分in和exist select * from 表A where id in (select id from 表B)这句相当于select from 表A where exists(select from 表B where 表B.id=表A.id)对于表A的每一条数据,都执行select * from 表B where 表B.id=表A.id的存在性判断,如果表B中存在表A当前行相同的id,则exists为真,该行显示,否则不显示 区分in和exists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询。 所以IN适合于外表大而内表小的情况;EXISTS适合于外表小而内表大的情况复杂多表尽量少用join MySQL 的优势在于简单,但这在某些方面其实也是其劣势。MySQL 优化器效率高,但是由于其统计信息的量有限,优化器工作过程出现偏差的可能性也就更多。对于复杂的多表 Join,一方面由于其优化器受限,再者在 Join 这方面所下的功夫还不够,所以性能表现离 Oracle 等关系型数据库前辈还是有一定距离。但如果是简单的单表查询,这一差距就会极小甚至在有些场景下要优于这些数据库前辈。尽量用join代替子查询 虽然 Join 性能并不佳,但是和 MySQL 的子查询比起来还是有非常大的性能优势。 MySQL需要为内层查询语句的查询结果建立一个临时表。然后外层查询语句在临时表中查询记录。查询完毕后,MySQL需要插销这些临时表。所以在MySQL中可以使用连接查询来代替子查询。连接查询不需要建立临时表,其速度比子查询要快。尽量少排序 排序操作会消耗较多的 CPU 资源,所以减少排序可以在缓存命中率高等 IO 能力足够的场景下会较大影响 SQL 的响应时间。 对于MySQL来说,减少排序有多种办法,比如: 上面误区中提到的通过利用索引来排序的方式进行优化 减少参与排序的记录条数 非必要不对数据进行排序尽量避免select * 大多数关系型数据库都是按照行(row)的方式存储,而数据存取操作都是以一个固定大小的IO单元(被称作 block 或者 page)为单位,一般为4KB,8KB… 大多数时候,每个IO单元中存储了多行,每行都是存储了该行的所有字段(lob等特殊类型字段除外)。 所以,我们是取一个字段还是多个字段,实际上数据库在表中需要访问的数据量其实是一样的。 也有例外情况,那就是我们的这个查询在索引中就可以完成,也就是说当只取 a,b两个字段的时候,不需要回表,而c这个字段不在使用的索引中,需要回表取得其数据。在这样的情况下,二者的IO量会有较大差异。尽量少or 当 where 子句中存在多个条件以“或”并存的时候,MySQL 的优化器并没有很好的解决其执行计划优化问题,再加上 MySQL 特有的 SQL 与 Storage 分层架构方式,造成了其性能比较低下,很多时候使用 union all 或者是union(必要的时候)的方式来代替“or”会得到更好的效果。尽量用 union all 代替 union union 和 union all 的差异主要是前者需要将两个(或者多个)结果集合并后再进行唯一性过滤操作,这就会涉及到排序,增加大量的 CPU 运算,加大资源消耗及延迟。所以当我们可以确认不可能出现重复结果集或者不在乎重复结果集的时候,尽量使用 union all 而不是 union。尽量早过滤 在 SQL 编写中同样可以使用这一原则来优化一些 Join 的 SQL。比如我们在多个表进行分页数据查询的时候,我们最好是能够在一个表上先过滤好数据分好页,然后再用分好页的结果集与另外的表 Join,这样可以尽可能多的减少不必要的 IO 操作,大大节省 IO 操作所消耗的时间。避免类型转换 这里所说的“类型转换”是指 where 子句中出现 column 字段的类型和传入的参数类型不一致的时候发生的类型转换: 人为在column_name 上通过转换函数进行转换直接导致 MySQL(实际上其他数据库也会有同样的问题)无法使用索引,如果非要转换,应该在传入的参数上进行转换,由数据库自己进行转换, 如果我们传入的数据类型和字段类型不一致,同时我们又没有做任何类型转换处理,MySQL 可能会自己对我们的数据进行类型转换操作,也可能不进行处理而交由存储引擎去处理,这样一来,就会出现索引无法使用的情况而造成执行计划问题。优先优化高并发的 SQL,而不是执行频率低某些“大”SQL 对于破坏性来说,高并发的 SQL 总是会比低频率的来得大,因为高并发的 SQL 一旦出现问题,甚至不会给我们任何喘息的机会就会将系统压跨。而对于一些虽然需要消耗大量 IO 而且响应很慢的 SQL,由于频率低,即使遇到,最多就是让整个系统响应慢一点,但至少可能撑一会儿,让我们有缓冲的机会。从全局出发优化,而不是片面调整 尤其是在通过调整索引优化 SQL 的执行计划的时候,千万不能顾此失彼,因小失大。尽可能对每一条运行在数据库中的SQL进行 explain 知道 SQL 的执行计划才能判断是否有优化余地,才能判断是否存在执行计划问题。在对数据库中运行的 SQL 进行了一段时间的优化之后,很明显的问题 SQL 可能已经很少了,大多都需要去发掘,这时候就需要进行大量的 explain 操作收集执行计划,并判断是否需要进行优化。尽量避免where子句中对字段进行null值的判断 会导致引擎放弃索引,进而进行全表扫描。 尽量不要给数据库留null值,尽可能地使用not null填充数据库。可以为每个null型的字段设置一个和null对应的实际内容表述。避免在where中使用!=, >, <操作符 否则引擎放弃使用索引,进行全表扫描。常用查询字段建索引避免在where中使用or imagein和not in关键词慎用,容易导致全表扫面 对连续的数值尽量用between通配符查询也容易导致全表扫描避免在where子句中使用局部变量 sql只有在运行时才解析局部变量。而优化程序必须在编译时访问执行计划,这时并不知道变量值,所以无法作为索引的输入项。 image避免在where子句中对字段进行表达式操作 会导致引擎放弃使用索引 image避免在where子句中对字段进行函数操作 image不要where子句的‘=’左边进行函数、算术运算或其他表达式运算 系统可能无法正确使用索引避免update全部字段 只update需要的字段。频繁调用会引起明显的性能消耗,同时带来大量日志。索引不是越多越好 一个表的索引数最好不要超过6个尽量使用数字型字段而非字符型 因为处理查询和连接时会逐个比较字符串的每个字符,而对于数字型而言只需要比较一次就够了。尽可能用varchar/nvarchar代替char/nchar 变长字段存储空间小,对于查询来说,在一个相对较小的字段内搜索效率更高。。。?避免频繁创建和删除临时表,减少系统表资源消耗select into和create table 新建临时表时,如果一次性插入数据量很大,使用select into代替create table,避免造成大量log,以提高速度。 如果数据量不大,为了缓和系统表的资源,先create table,再insert。 拆分大的DELETE和INSERT语句 因为这两个操作是会锁表的,对于高访问量的站点来说,锁表时间内积累的访问数、数据库连接、打开的文件数等等,可能不仅仅让WEB服务崩溃,还会让整台服务器马上挂了。 所以,一定要拆分,使用LIMIT条件休眠一段时间,批量处理。

wangccsy 2019-12-02 01:50:30 0 浏览量 回答数 0

问题

最佳实践 -MySQL-为应用选择和创建最佳索引,加速数据读取

李沃晟 2019-12-01 21:40:05 575 浏览量 回答数 0

问题

如何使用SELECT数据操作语言

云栖大讲堂 2019-12-01 21:28:48 1030 浏览量 回答数 0

回答

92题 一般来说,建立INDEX有以下益处:提高查询效率;建立唯一索引以保证数据的唯一性;设计INDEX避免排序。 缺点,INDEX的维护有以下开销:叶节点的‘分裂’消耗;INSERT、DELETE和UPDATE操作在INDEX上的维护开销;有存储要求;其他日常维护的消耗:对恢复的影响,重组的影响。 需要建立索引的情况:为了建立分区数据库的PATITION INDEX必须建立; 为了保证数据约束性需要而建立的INDEX必须建立; 为了提高查询效率,则考虑建立(是否建立要考虑相关性能及维护开销); 考虑在使用UNION,DISTINCT,GROUP BY,ORDER BY等字句的列上加索引。 91题 作用:加快查询速度。原则:(1) 如果某属性或属性组经常出现在查询条件中,考虑为该属性或属性组建立索引;(2) 如果某个属性常作为最大值和最小值等聚集函数的参数,考虑为该属性建立索引;(3) 如果某属性经常出现在连接操作的连接条件中,考虑为该属性或属性组建立索引。 90题 快照Snapshot是一个文件系统在特定时间里的镜像,对于在线实时数据备份非常有用。快照对于拥有不能停止的应用或具有常打开文件的文件系统的备份非常重要。对于只能提供一个非常短的备份时间而言,快照能保证系统的完整性。 89题 游标用于定位结果集的行,通过判断全局变量@@FETCH_STATUS可以判断是否到了最后,通常此变量不等于0表示出错或到了最后。 88题 事前触发器运行于触发事件发生之前,而事后触发器运行于触发事件发生之后。通常事前触发器可以获取事件之前和新的字段值。语句级触发器可以在语句执行前或后执行,而行级触发在触发器所影响的每一行触发一次。 87题 MySQL可以使用多个字段同时建立一个索引,叫做联合索引。在联合索引中,如果想要命中索引,需要按照建立索引时的字段顺序挨个使用,否则无法命中索引。具体原因为:MySQL使用索引时需要索引有序,假设现在建立了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,如果name相同,则按照age排序,如果age的值也相等,则按照school进行排序。因此在建立联合索引的时候应该注意索引列的顺序,一般情况下,将查询需求频繁或者字段选择性高的列放在前面。此外可以根据特例的查询或者表结构进行单独的调整。 86题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 85题 存储过程是一组Transact-SQL语句,在一次编译后可以执行多次。因为不必重新编译Transact-SQL语句,所以执行存储过程可以提高性能。触发器是一种特殊类型的存储过程,不由用户直接调用。创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行。 84题 存储过程是用户定义的一系列SQL语句的集合,涉及特定表或其它对象的任务,用户可以调用存储过程,而函数通常是数据库已定义的方法,它接收参数并返回某种类型的值并且不涉及特定用户表。 83题 减少表连接,减少复杂 SQL,拆分成简单SQL。减少排序:非必要不排序,利用索引排序,减少参与排序的记录数。尽量避免 select *。尽量用 join 代替子查询。尽量少使用 or,使用 in 或者 union(union all) 代替。尽量用 union all 代替 union。尽量早的将无用数据过滤:选择更优的索引,先分页再Join…。避免类型转换:索引失效。优先优化高并发的 SQL,而不是执行频率低某些“大”SQL。从全局出发优化,而不是片面调整。尽可能对每一条SQL进行 explain。 82题 如果条件中有or,即使其中有条件带索引也不会使用(要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引)。对于多列索引,不是使用的第一部分,则不会使用索引。like查询是以%开头。如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引。如果mysql估计使用全表扫描要比使用索引快,则不使用索引。例如,使用<>、not in 、not exist,对于这三种情况大多数情况下认为结果集很大,MySQL就有可能不使用索引。 81题 主键不能重复,不能为空,唯一键不能重复,可以为空。建立主键的目的是让外键来引用。一个表最多只有一个主键,但可以有很多唯一键。 80题 空值('')是不占用空间的,判断空字符用=''或者<>''来进行处理。NULL值是未知的,且占用空间,不走索引;判断 NULL 用 IS NULL 或者 is not null ,SQL 语句函数中可以使用 ifnull ()函数来进行处理。无法比较 NULL 和 0;它们是不等价的。无法使用比较运算符来测试 NULL 值,比如 =, <, 或者 <>。NULL 值可以使用 <=> 符号进行比较,该符号与等号作用相似,但对NULL有意义。进行 count ()统计某列的记录数的时候,如果采用的 NULL 值,会被系统自动忽略掉,但是空值是统计到其中。 79题 HEAP表是访问数据速度最快的MySQL表,他使用保存在内存中的散列索引。一旦服务器重启,所有heap表数据丢失。BLOB或TEXT字段是不允许的。只能使用比较运算符=,<,>,=>,= <。HEAP表不支持AUTO_INCREMENT。索引不可为NULL。 78题 如果想输入字符为十六进制数字,可以输入带有单引号的十六进制数字和前缀(X),或者只用(Ox)前缀输入十六进制数字。如果表达式上下文是字符串,则十六进制数字串将自动转换为字符串。 77题 Mysql服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。 76题 在缺省模式下,MYSQL是autocommit模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql是不支持事务的。但是如果你的MYSQL表类型是使用InnoDB Tables 或 BDB tables的话,你的MYSQL就可以使用事务处理,使用SET AUTOCOMMIT=0就可以使MYSQL允许在非autocommit模式,在非autocommit模式下,你必须使用COMMIT来提交你的更改,或者用ROLLBACK来回滚你的更改。 75题 它会停止递增,任何进一步的插入都将产生错误,因为密钥已被使用。 74题 创建索引的时候尽量使用唯一性大的列来创建索引,由于使用b+tree做为索引,以innodb为例,一个树节点的大小由“innodb_page_size”,为了减少树的高度,同时让一个节点能存放更多的值,索引列尽量在整数类型上创建,如果必须使用字符类型,也应该使用长度较少的字符类型。 73题 当MySQL单表记录数过大时,数据库的CRUD性能会明显下降,一些常见的优化措施如下: 限定数据的范围: 务必禁止不带任何限制数据范围条件的查询语句。比如:我们当用户在查询订单历史的时候,我们可以控制在一个月的范围内。读/写分离: 经典的数据库拆分方案,主库负责写,从库负责读。垂直分区: 根据数据库里面数据表的相关性进行拆分。简单来说垂直拆分是指数据表列的拆分,把一张列比较多的表拆分为多张表。水平分区: 保持数据表结构不变,通过某种策略存储数据分片。这样每一片数据分散到不同的表或者库中,达到了分布式的目的。水平拆分可以支撑非常大的数据量。 72题 乐观锁失败后会抛出ObjectOptimisticLockingFailureException,那么我们就针对这块考虑一下重试,自定义一个注解,用于做切面。针对注解进行切面,设置最大重试次数n,然后超过n次后就不再重试。 71题 一致性非锁定读讲的是一条记录被加了X锁其他事务仍然可以读而不被阻塞,是通过innodb的行多版本实现的,行多版本并不是实际存储多个版本记录而是通过undo实现(undo日志用来记录数据修改前的版本,回滚时会用到,用来保证事务的原子性)。一致性锁定读讲的是我可以通过SELECT语句显式地给一条记录加X锁从而保证特定应用场景下的数据一致性。 70题 数据库引擎:尤其是mysql数据库只有是InnoDB引擎的时候事物才能生效。 show engines 查看数据库默认引擎;SHOW TABLE STATUS from 数据库名字 where Name='表名' 如下;SHOW TABLE STATUS from rrz where Name='rrz_cust';修改表的引擎alter table table_name engine=innodb。 69题 如果是等值查询,那么哈希索引明显有绝对优势,因为只需要经过一次算法即可找到相应的键值;当然了,这个前提是,键值都是唯一的。如果键值不是唯一的,就需要先找到该键所在位置,然后再根据链表往后扫描,直到找到相应的数据;如果是范围查询检索,这时候哈希索引就毫无用武之地了,因为原先是有序的键值,经过哈希算法后,有可能变成不连续的了,就没办法再利用索引完成范围查询检索;同理,哈希索引也没办法利用索引完成排序,以及like ‘xxx%’ 这样的部分模糊查询(这种部分模糊查询,其实本质上也是范围查询);哈希索引也不支持多列联合索引的最左匹配规则;B+树索引的关键字检索效率比较平均,不像B树那样波动幅度大,在有大量重复键值情况下,哈希索引的效率也是极低的,因为存在所谓的哈希碰撞问题。 68题 decimal精度比float高,数据处理比float简单,一般优先考虑,但float存储的数据范围大,所以范围大的数据就只能用它了,但要注意一些处理细节,因为不精确可能会与自己想的不一致,也常有关于float 出错的问题。 67题 datetime、timestamp精确度都是秒,datetime与时区无关,存储的范围广(1001-9999),timestamp与时区有关,存储的范围小(1970-2038)。 66题 Char使用固定长度的空间进行存储,char(4)存储4个字符,根据编码方式的不同占用不同的字节,gbk编码方式,不论是中文还是英文,每个字符占用2个字节的空间,utf8编码方式,每个字符占用3个字节的空间。Varchar保存可变长度的字符串,使用额外的一个或两个字节存储字符串长度,varchar(10),除了需要存储10个字符,还需要1个字节存储长度信息(10),超过255的长度需要2个字节来存储。char和varchar后面如果有空格,char会自动去掉空格后存储,varchar虽然不会去掉空格,但在进行字符串比较时,会去掉空格进行比较。Varbinary保存变长的字符串,后面不会补\0。 65题 首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表。 64题 建立索引的时候一般要考虑到字段的使用频率,经常作为条件进行查询的字段比较适合。如果需要建立联合索引的话,还需要考虑联合索引中的顺序。此外也要考虑其他方面,比如防止过多的所有对表造成太大的压力。这些都和实际的表结构以及查询方式有关。 63题 存储过程是一些预编译的SQL语句。1、更加直白的理解:存储过程可以说是一个记录集,它是由一些T-SQL语句组成的代码块,这些T-SQL语句代码像一个方法一样实现一些功能(对单表或多表的增删改查),然后再给这个代码块取一个名字,在用到这个功能的时候调用他就行了。2、存储过程是一个预编译的代码块,执行效率比较高,一个存储过程替代大量T_SQL语句 ,可以降低网络通信量,提高通信速率,可以一定程度上确保数据安全。 62题 密码散列、盐、用户身份证号等固定长度的字符串应该使用char而不是varchar来存储,这样可以节省空间且提高检索效率。 61题 推荐使用自增ID,不要使用UUID。因为在InnoDB存储引擎中,主键索引是作为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及全部的数据(按照顺序),如果主键索引是自增ID,那么只需要不断向后排列即可,如果是UUID,由于到来的ID与原来的大小不确定,会造成非常多的数据插入,数据移动,然后导致产生很多的内存碎片,进而造成插入性能的下降。总之,在数据量大一些的情况下,用自增主键性能会好一些。 60题 char是一个定长字段,假如申请了char(10)的空间,那么无论实际存储多少内容。该字段都占用10个字符,而varchar是变长的,也就是说申请的只是最大长度,占用的空间为实际字符长度+1,最后一个字符存储使用了多长的空间。在检索效率上来讲,char > varchar,因此在使用中,如果确定某个字段的值的长度,可以使用char,否则应该尽量使用varchar。例如存储用户MD5加密后的密码,则应该使用char。 59题 一. read uncommitted(读取未提交数据) 即便是事务没有commit,但是我们仍然能读到未提交的数据,这是所有隔离级别中最低的一种。 二. read committed(可以读取其他事务提交的数据)---大多数数据库默认的隔离级别 当前会话只能读取到其他事务提交的数据,未提交的数据读不到。 三. repeatable read(可重读)---MySQL默认的隔离级别 当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。 四. serializable(串行化) 其他会话对该表的写操作将被挂起。可以看到,这是隔离级别中最严格的,但是这样做势必对性能造成影响。所以在实际的选用上,我们要根据当前具体的情况选用合适的。 58题 B+树的高度一般为2-4层,所以查找记录时最多只需要2-4次IO,相对二叉平衡树已经大大降低了。范围查找时,能通过叶子节点的指针获取数据。例如查找大于等于3的数据,当在叶子节点中查到3时,通过3的尾指针便能获取所有数据,而不需要再像二叉树一样再获取到3的父节点。 57题 因为事务在修改页时,要先记 undo,在记 undo 之前要记 undo 的 redo, 然后修改数据页,再记数据页修改的 redo。 Redo(里面包括 undo 的修改) 一定要比数据页先持久化到磁盘。 当事务需要回滚时,因为有 undo,可以把数据页回滚到前镜像的状态,崩溃恢复时,如果 redo log 中事务没有对应的 commit 记录,那么需要用 undo把该事务的修改回滚到事务开始之前。 如果有 commit 记录,就用 redo 前滚到该事务完成时并提交掉。 56题 redo log是物理日志,记录的是"在某个数据页上做了什么修改"。 binlog是逻辑日志,记录的是这个语句的原始逻辑,比如"给ID=2这一行的c字段加1"。 redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。 redo log是循环写的,空间固定会用完:binlog 是可以追加写入的。"追加写"是指binlog文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。 最开始 MySQL 里并没有 InnoDB 引擎,MySQL 自带的引擎是 MyISAM,但是 MyISAM 没有 crash-safe 的能力,binlog日志只能用于归档。而InnoDB 是另一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,所以 InnoDB 使用另外一套日志系统,也就是 redo log 来实现 crash-safe 能力。 55题 重做日志(redo log)      作用:确保事务的持久性,防止在发生故障,脏页未写入磁盘。重启数据库会进行redo log执行重做,达到事务一致性。 回滚日志(undo log)  作用:保证数据的原子性,保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。 二进 制日志(binlog)    作用:用于主从复制,实现主从同步;用于数据库的基于时间点的还原。 错误日志(errorlog) 作用:Mysql本身启动,停止,运行期间发生的错误信息。 慢查询日志(slow query log)  作用:记录执行时间过长的sql,时间阈值可以配置,只记录执行成功。 一般查询日志(general log)    作用:记录数据库的操作明细,默认关闭,开启后会降低数据库性能 。 中继日志(relay log) 作用:用于数据库主从同步,将主库发来的bin log保存在本地,然后从库进行回放。 54题 MySQL有三种锁的级别:页级、表级、行级。 表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。 行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。 页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。 死锁: 是指两个或两个以上的进程在执行过程中。因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。 死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。 那么对应的解决死锁问题的关键就是:让不同的session加锁有次序。死锁的解决办法:1.查出的线程杀死。2.设置锁的超时时间。3.指定获取锁的顺序。 53题 当多个用户并发地存取数据时,在数据库中就会产生多个事务同时存取同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性(脏读,不可重复读,幻读等),可能产生死锁。 乐观锁:乐观锁不是数据库自带的,需要我们自己去实现。 悲观锁:在进行每次操作时都要通过获取锁才能进行对相同数据的操作。 共享锁:加了共享锁的数据对象可以被其他事务读取,但不能修改。 排他锁:当数据对象被加上排它锁时,一个事务必须得到锁才能对该数据对象进行访问,一直到事务结束锁才被释放。 行锁:就是给某一条记录加上锁。 52题 Mysql是关系型数据库,MongoDB是非关系型数据库,数据存储结构的不同。 51题 关系型数据库优点:1.保持数据的一致性(事务处理)。 2.由于以标准化为前提,数据更新的开销很小。 3. 可以进行Join等复杂查询。 缺点:1、为了维护一致性所付出的巨大代价就是其读写性能比较差。 2、固定的表结构。 3、高并发读写需求。 4、海量数据的高效率读写。 非关系型数据库优点:1、无需经过sql层的解析,读写性能很高。 2、基于键值对,数据没有耦合性,容易扩展。 3、存储数据的格式:nosql的存储格式是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,而关系型数据库则只支持基础类型。 缺点:1、不提供sql支持,学习和使用成本较高。 2、无事务处理,附加功能bi和报表等支持也不好。 redis与mongoDB的区别: 性能:TPS方面redis要大于mongodb。 可操作性:mongodb支持丰富的数据表达,索引,redis较少的网络IO次数。 可用性:MongoDB优于Redis。 一致性:redis事务支持比较弱,mongoDB不支持事务。 数据分析:mongoDB内置了数据分析的功能(mapreduce)。 应用场景:redis数据量较小的更性能操作和运算上,MongoDB主要解决海量数据的访问效率问题。 50题 如果Redis被当做缓存使用,使用一致性哈希实现动态扩容缩容。如果Redis被当做一个持久化存储使用,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化。否则的话(即Redis节点需要动态变化的情况),必须使用可以在运行时进行数据再平衡的一套系统,而当前只有Redis集群可以做到这样。 49题 分区可以让Redis管理更大的内存,Redis将可以使用所有机器的内存。如果没有分区,你最多只能使用一台机器的内存。分区使Redis的计算能力通过简单地增加计算机得到成倍提升,Redis的网络带宽也会随着计算机和网卡的增加而成倍增长。 48题 除了缓存服务器自带的缓存失效策略之外(Redis默认的有6种策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种: 1.定时去清理过期的缓存; 2.当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存。 两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂!具体用哪种方案,可以根据应用场景来权衡。 47题 Redis提供了两种方式来作消息队列: 一个是使用生产者消费模式模式:会让一个或者多个客户端监听消息队列,一旦消息到达,消费者马上消费,谁先抢到算谁的,如果队列里没有消息,则消费者继续监听 。另一个就是发布订阅者模式:也是一个或多个客户端订阅消息频道,只要发布者发布消息,所有订阅者都能收到消息,订阅者都是平等的。 46题 Redis的数据结构列表(list)可以实现延时队列,可以通过队列和栈来实现。blpop/brpop来替换lpop/rpop,blpop/brpop阻塞读在队列没有数据的时候,会立即进入休眠状态,一旦数据到来,则立刻醒过来。Redis的有序集合(zset)可以用于实现延时队列,消息作为value,时间作为score。Zrem 命令用于移除有序集中的一个或多个成员,不存在的成员将被忽略。当 key 存在但不是有序集类型时,返回一个错误。 45题 1.热点数据缓存:因为Redis 访问速度块、支持的数据类型比较丰富。 2.限时业务:expire 命令设置 key 的生存时间,到时间后自动删除 key。 3.计数器:incrby 命令可以实现原子性的递增。 4.排行榜:借助 SortedSet 进行热点数据的排序。 5.分布式锁:利用 Redis 的 setnx 命令进行。 6.队列机制:有 list push 和 list pop 这样的命令。 44题 一致哈希 是一种特殊的哈希算法。在使用一致哈希算法后,哈希表槽位数(大小)的改变平均只需要对 K/n 个关键字重新映射,其中K是关键字的数量, n是槽位数量。然而在传统的哈希表中,添加或删除一个槽位的几乎需要对所有关键字进行重新映射。 43题 RDB的优点:适合做冷备份;读写服务影响小,reids可以保持高性能;重启和恢复redis进程,更加快速。RDB的缺点:宕机会丢失最近5分钟的数据;文件特别大时可能会暂停数毫秒,或者甚至数秒。 AOF的优点:每个一秒执行fsync操作,最多丢失1秒钟的数据;以append-only模式写入,没有任何磁盘寻址的开销;文件过大时,不会影响客户端读写;适合做灾难性的误删除的紧急恢复。AOF的缺点:AOF日志文件比RDB数据快照文件更大,支持写QPS比RDB支持的写QPS低;比RDB脆弱,容易有bug。 42题 对于Redis而言,命令的原子性指的是:一个操作的不可以再分,操作要么执行,要么不执行。Redis的操作之所以是原子性的,是因为Redis是单线程的。而在程序中执行多个Redis命令并非是原子性的,这也和普通数据库的表现是一样的,可以用incr或者使用Redis的事务,或者使用Redis+Lua的方式实现。对Redis来说,执行get、set以及eval等API,都是一个一个的任务,这些任务都会由Redis的线程去负责执行,任务要么执行成功,要么执行失败,这就是Redis的命令是原子性的原因。 41题 (1)twemproxy,使用方式简单(相对redis只需修改连接端口),对旧项目扩展的首选。(2)codis,目前用的最多的集群方案,基本和twemproxy一致的效果,但它支持在节点数改变情况下,旧节点数据可恢复到新hash节点。(3)redis cluster3.0自带的集群,特点在于他的分布式算法不是一致性hash,而是hash槽的概念,以及自身支持节点设置从节点。(4)在业务代码层实现,起几个毫无关联的redis实例,在代码层,对key进行hash计算,然后去对应的redis实例操作数据。这种方式对hash层代码要求比较高,考虑部分包括,节点失效后的代替算法方案,数据震荡后的自动脚本恢复,实例的监控,等等。 40题 (1) Master最好不要做任何持久化工作,如RDB内存快照和AOF日志文件 (2) 如果数据比较重要,某个Slave开启AOF备份数据,策略设置为每秒同步一次 (3) 为了主从复制的速度和连接的稳定性,Master和Slave最好在同一个局域网内 (4) 尽量避免在压力很大的主库上增加从库 (5) 主从复制不要用图状结构,用单向链表结构更为稳定,即:Master <- Slave1 <- Slave2 <- Slave3...这样的结构方便解决单点故障问题,实现Slave对Master的替换。如果Master挂了,可以立刻启用Slave1做Master,其他不变。 39题 比如订单管理,热数据:3个月内的订单数据,查询实时性较高;温数据:3个月 ~ 12个月前的订单数据,查询频率不高;冷数据:1年前的订单数据,几乎不会查询,只有偶尔的查询需求。热数据使用mysql进行存储,需要分库分表;温数据可以存储在ES中,利用搜索引擎的特性基本上也可以做到比较快的查询;冷数据可以存放到Hive中。从存储形式来说,一般情况冷数据存储在磁带、光盘,热数据一般存放在SSD中,存取速度快,而温数据可以存放在7200转的硬盘。 38题 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。 37题 分层架构设计,有一条准则:站点层、服务层要做到无数据无状态,这样才能任意的加节点水平扩展,数据和状态尽量存储到后端的数据存储服务,例如数据库服务或者缓存服务。显然进程内缓存违背了这一原则。 36题 更新数据的时候,根据数据的唯一标识,将操作路由之后,发送到一个 jvm 内部队列中。读取数据的时候,如果发现数据不在缓存中,那么将重新读取数据+更新缓存的操作,根据唯一标识路由之后,也发送同一个 jvm 内部队列中。一个队列对应一个工作线程,每个工作线程串行拿到对应的操作,然后一条一条的执行。 35题 redis分布式锁加锁过程:通过setnx向特定的key写入一个随机值,并同时设置失效时间,写值成功既加锁成功;redis分布式锁解锁过程:匹配随机值,删除redis上的特点key数据,要保证获取数据、判断一致以及删除数据三个操作是原子的,为保证原子性一般使用lua脚本实现;在此基础上进一步优化的话,考虑使用心跳检测对锁的有效期进行续期,同时基于redis的发布订阅优雅的实现阻塞式加锁。 34题 volatile-lru:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选最近最少使用的数据淘汰。 volatile-ttl:当内存不足以容纳写入数据时,从已设置过期时间的数据集中挑选将要过期的数据淘汰。 volatile-random:当内存不足以容纳写入数据时,从已设置过期时间的数据集中任意选择数据淘汰。 allkeys-lru:当内存不足以容纳写入数据时,从数据集中挑选最近最少使用的数据淘汰。 allkeys-random:当内存不足以容纳写入数据时,从数据集中任意选择数据淘汰。 noeviction:禁止驱逐数据,当内存使用达到阈值的时候,所有引起申请内存的命令会报错。 33题 定时过期:每个设置过期时间的key都需要创建一个定时器,到过期时间就会立即清除。该策略可以立即清除过期的数据,对内存很友好;但是会占用大量的CPU资源去处理过期的数据,从而影响缓存的响应时间和吞吐量。 惰性过期:只有当访问一个key时,才会判断该key是否已过期,过期则清除。该策略可以最大化地节省CPU资源,却对内存非常不友好。极端情况可能出现大量的过期key没有再次被访问,从而不会被清除,占用大量内存。 定期过期:每隔一定的时间,会扫描一定数量的数据库的expires字典中一定数量的key,并清除其中已过期的key。该策略是前两者的一个折中方案。通过调整定时扫描的时间间隔和每次扫描的限定耗时,可以在不同情况下使得CPU和内存资源达到最优的平衡效果。 32题 缓存击穿,一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。如何避免:在访问key之前,采用SETNX(set if not exists)来设置另一个短期key来锁住当前key的访问,访问结束再删除该短期key。 31题 缓存雪崩,是指在某一个时间段,缓存集中过期失效。大量的key设置了相同的过期时间,导致在缓存在同一时刻全部失效,造成瞬时DB请求量大、压力骤增,引起雪崩。而缓存服务器某个节点宕机或断网,对数据库服务器造成的压力是不可预知的,很有可能瞬间就把数据库压垮。如何避免:1.redis高可用,搭建redis集群。2.限流降级,在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。3.数据预热,在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间。 30题 缓存穿透,是指查询一个数据库一定不存在的数据。正常的使用缓存流程大致是,数据查询先进行缓存查询,如果key不存在或者key已经过期,再对数据库进行查询,并把查询到的对象,放进缓存。如果数据库查询对象为空,则不放进缓存。一些恶意的请求会故意查询不存在的 key,请求量很大,对数据库造成压力,甚至压垮数据库。 如何避免:1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该 key 对应的数据 insert 了之后清理缓存。2:对一定不存在的 key 进行过滤。可以把所有的可能存在的 key 放到一个大的 Bitmap 中,查询时通过该 bitmap 过滤。 29题 1.memcached 所有的值均是简单的字符串,redis 作为其替代者,支持更为丰富的数据类型。 2.redis 的速度比 memcached 快很多。 3.redis 可以持久化其数据。 4.Redis支持数据的备份,即master-slave模式的数据备份。 5.Redis采用VM机制。 6.value大小:redis最大可以达到1GB,而memcache只有1MB。 28题 Spring Boot 推荐使用 Java 配置而非 XML 配置,但是 Spring Boot 中也可以使用 XML 配置,通过spring提供的@ImportResource来加载xml配置。例如:@ImportResource({"classpath:some-context.xml","classpath:another-context.xml"}) 27题 Spring像一个大家族,有众多衍生产品例如Spring Boot,Spring Security等等,但他们的基础都是Spring的IOC和AOP,IOC提供了依赖注入的容器,而AOP解决了面向切面的编程,然后在此两者的基础上实现了其他衍生产品的高级功能。Spring MVC是基于Servlet的一个MVC框架,主要解决WEB开发的问题,因为 Spring的配置非常复杂,各种xml,properties处理起来比较繁琐。Spring Boot遵循约定优于配置,极大降低了Spring使用门槛,又有着Spring原本灵活强大的功能。总结:Spring MVC和Spring Boot都属于Spring,Spring MVC是基于Spring的一个MVC框架,而Spring Boot是基于Spring的一套快速开发整合包。 26题 YAML 是 "YAML Ain't a Markup Language"(YAML 不是一种标记语言)的递归缩写。YAML 的配置文件后缀为 .yml,是一种人类可读的数据序列化语言,可以简单表达清单、散列表,标量等数据形态。它通常用于配置文件,与属性文件相比,YAML文件就更加结构化,而且更少混淆。可以看出YAML具有分层配置数据。 25题 Spring Boot有3种热部署方式: 1.使用springloaded配置pom.xml文件,使用mvn spring-boot:run启动。 2.使用springloaded本地加载启动,配置jvm参数-javaagent:<jar包地址> -noverify。 3.使用devtools工具包,操作简单,但是每次需要重新部署。 用

游客ih62co2qqq5ww 2020-03-27 23:56:48 0 浏览量 回答数 0

问题

play 框架中如何在anorm 解析数据库结果时进行datetime格式转换?

蛮大人123 2019-12-01 19:52:09 1609 浏览量 回答数 0

回答

对于MySQL 8+:使用递归with语法。 对于MySQL 5.x:使用内联变量,路径ID或自联接。 MySQL 8+ with recursive cte (id, name, parent_id) as ( select id, name, parent_id from products where parent_id = 19 union all select p.id, p.name, p.parent_id from products p inner join cte on p.parent_id = cte.id ) select * from cte; 中指定的值parent_id = 19应设置为id您要选择其所有后代的父级的。 MySQL 5.x 对于不支持通用表表达式的MySQL版本(最高5.7版),您可以通过以下查询来实现: select id, name, parent_id from (select * from products order by parent_id, id) products_sorted, (select @pv := '19') initialisation where find_in_set(parent_id, @pv) and length(@pv := concat(@pv, ',', id)) 这是一个小提琴。 在此,@pv := '19'应将中指定的值设置为id要选择其所有后代的父级的值。 如果父母有多个孩子,这也将起作用。但是,要求每个记录都满足条件parent_id < id,否则结果将不完整。 查询中的变量分配 该查询使用特定的MySQL语法:在执行过程中分配和修改变量。对执行顺序进行了一些假设: 该from子句首先被评估。这就是@pv初始化的地方。 where按照从from别名检索的顺序为每个记录评估该子句。因此,在这里将条件放在仅包括已将其父级标识为后代树的记录中(主要父级的所有后代都逐渐添加到中@pv)。 此where子句中的条件按顺序进行评估,一旦确定了总结果,评估就会中断。因此,第二个条件必须排在第二位,因为它将添加id到父列表,并且仅在id通过第一个条件时才应发生。length即使该pv字符串由于某种原因会产生虚假的值,也只能调用该函数以确保此条件始终为true 。 总而言之,人们可能会发现这些假设过于冒险,无法依靠。该文档警告: 您可能会得到期望的结果,但这不能保证涉及用户变量的表达式的求值顺序不确定。 因此,即使它与上面的查询一致地工作,评估顺序仍可能会更改,例如,当您添加条件或将此查询用作较大查询中的视图或子查询时。这是一个“功能”,将在将来的MySQL版本中删除: MySQL的早期版本使得可以在以外的语句中为用户变量赋值SET。MySQL 8.0支持此功能以实现向后兼容,但是在将来的MySQL版本中可能会删除该功能。 如上所述,从MySQL 8.0开始,您应该使用递归with语法。 效率 对于非常大的数据集,此解决方案可能会变慢,因为该find_in_set操作不是在列表中查找数字的最理想方法,当然,在列表大小与返回的记录数量相同数量级的列表中,查找方法肯定不是。 选择1 :with recursive,connect by 越来越多的数据库执行SQL:1999 ISO标准WITH [RECURSIVE]语法的递归查询(如Postgres的8.4+,SQL Server的2005+,DB2,甲骨文11gR2的+,SQLite的3.8.4+,火鸟2.1+,H2,的HyperSQL 2.1.0+,Teradata的,MariaDB 10.2.2+)。从8.0版开始,MySQL也支持它。有关使用的语法,请参见此答案的顶部。 一些数据库具有用于分层查找的替代非标准语法,例如Oracle,DB2,Informix,CUBRID和其他数据库CONNECT BY上可用的子句。 MySQL 5.7版不提供这种功能。如果您的数据库引擎提供了这种语法,或者您可以迁移到该语法,那么这无疑是最佳选择。如果不是,则还考虑以下替代方法。 备选方案2:路径样式标识符 如果您要分配id包含层次结构信息的值(路径),事情就会变得容易得多。例如,在您的情况下,可能如下所示: ID | NAME 19 | category1 19/1 | category2 19/1/1 | category3 19/1/1/1 | category4 然后,您select将如下所示: select id, name from products where id like '19/%' 选择3:重复的自我联接 如果您知道层次结构树的深度上限,则可以使用以下标准sql查询: select p6.parent_id as parent6_id, p5.parent_id as parent5_id, p4.parent_id as parent4_id, p3.parent_id as parent3_id, p2.parent_id as parent2_id, p1.parent_id as parent_id, p1.id as product_id, p1.name from products p1 left join products p2 on p2.id = p1.parent_id left join products p3 on p3.id = p2.parent_id left join products p4 on p4.id = p3.parent_id left join products p5 on p5.id = p4.parent_id left join products p6 on p6.id = p5.parent_id where 19 in (p1.parent_id, p2.parent_id, p3.parent_id, p4.parent_id, p5.parent_id, p6.parent_id) order by 1, 2, 3, 4, 5, 6, 7; 来源:stack overflow

保持可爱mmm 2020-05-08 10:15:00 0 浏览量 回答数 0

问题

SSH面试题

琴瑟 2019-12-01 21:46:22 3489 浏览量 回答数 0

问题

LM计算引擎 SELECT语法是什么?

nicenelly 2019-12-01 21:10:46 1307 浏览量 回答数 0

问题

LM计算引擎 SELECT语法是什么?

nicenelly 2019-12-01 21:25:16 961 浏览量 回答数 0

回答

简介 如果您听说过 Node,或者阅读过一些文章,宣称 Node 是多么多么的棒,那么您可能会想:“Node 究竟是什么东西?”尽管不是针对所有人的,但 Node 可能是某些人的正确选择。 为试图解释什么是 Node.js,本文探究了它能解决的问题,它如何工作,如何运行一个简单应用程序,最后,Node 何时是和何时不是一个好的解决方案。本文不涉及如何编写一个复杂的 Node 应用程序,也不是一份全面的 Node 教程。阅读本文应该有助于您决定是否应该学习 Node,以便将其用于您的业务。 Node 旨在解决什么问题? Node 公开宣称的目标是 “旨在提供一种简单的构建可伸缩网络程序的方法”。当前的服务器程序有什么问题?我们来做个数学题。在 Java™ 和 PHP 这类语言中,每个连接都会生成一个新线程,每个新线程可能需要 2 MB 配套内存。在一个拥有 8 GB RAM 的系统上,理论上最大的并发连接数量是 4,000 个用户。随着您的客户端基础的增长,您希望您的 web 应用程序支持更多用户,这样,您必须添加更多服务器。当然,这会增加业务成本,尤其是服务器成本、运输成本和人工成本。除这些成本上升外,还有一个技术问题:用户可能针对每个请求使用不同的服务器,因此,任何共享资源都必须在所有服务器之间共享。例如,在 Java 中,静态变量和缓存需要在每个服务器上的 JVMs 之间共享。这就是整个 web 应用程序架构中的瓶颈:一个服务器能够处理的并发连接的最大数量。 Node 解决这个问题的方法是:更改连接连接到服务器的方式。每个连接都创建一个进程,该进程不需要配套内存块,而不是为每个连接生成一个新的 OS 线程(并向其分配一些配套内存)。Node 声称它绝不会死锁,因为它根本不允许使用锁,它不会直接阻塞 I/O 调用。Node 还宣称,运行它的服务器能支持数万个并发连接。事实上,Node 通过将整个系统中的瓶颈从最大连接数量更改到单个系统的流量来改变服务器面貌。 现在您有了一个能处理数万条并发连接的程序,那么您能通过 Node 实际构建什么呢?如果您有一个 web 应用程序需要处理这么多连接,那将是一件很 “恐怖” 的事!那是一种 “如果您有这个问题,那么它根本不是问题” 的问题。在回答上面的问题之前,我们先看看 Node 如何工作以及它被设计的如何运行。 Node 肯定不是什么 没错,Node 是一个服务器程序。但是,它肯定不 像 Apache 或 Tomcat。那些服务器是独立服务器产品,可以立即安装并部署应用程序。通过这些产品,您可以在一分钟内启动并运行一个服务器。Node 肯定不是这种产品。Apache 能添加一个 PHP 模块来允许开发人员创建动态 web 页,使用 Tomcat 的程序员能部署 JSPs 来创建动态 web 页。Node 肯定不是这种类型。 在 Node 的早期阶段(当前是 version 0.4.6),它还不是一个 “运行就绪” 的服务器程序,您还不能安装它,向其中放置文件,拥有一个功能齐全的 web 服务器。即使是要实现 web 服务器在安装完成后启动并运行这个基本功能,也还需要做大量工作。 Node 如何工作 Node 本身运行 V8 JavaScript。等等,服务器上的 JavaScript?没错,您没有看错。服务器端 JavaScript 是一个相对较新的概念,这个概念是大约两年前在 developerWorks 上讨论 Aptana Jaxer 产品时提到的(参见 参考资料)。尽管 Jaxer 一直没有真正流行,但这个理念本身并不是遥不可及的 — 为何不能在服务器上使用客户机上使用的编程语言? 什么使 V8?V8 JavaScript 引擎是 Google 用于他们的 Chrome 浏览器的底层 JavaScript 引擎。很少有人考虑 JavaScript 在客户机上实际做了些什么?实际上,JavaScript 引擎负责解释并执行代码。使用 V8,Google 创建了一个以 C++ 编写的超快解释器,该解释器拥有另一个独特特征;您可以下载该引擎并将其嵌入任何 应用程序。它不仅限于在一个浏览器中运行。因此,Node 实际上使用 Google 编写的 V8 JavaScript 引擎并将其重建为在服务器上使用。太完美了!既然已经有一个不错的解决方案可用,为何还要创建一种新语言呢? 事件驱动编程 许多程序员接受的教育使他们认为,面向对象编程是完美的编程设计,而对其他编程方法不屑一顾。Node 使用一个所谓的事件驱动编程模型。 清单 1. 客户端上使用 jQuery 的事件驱动编程 复制代码 代码如下: // jQuery code on the client-side showing how Event-Driven programming works // When a button is pressed, an Event occurs - deal with it // directly right here in an anonymous function, where all the // necessary variables are present and can be referenced directly $("#myButton").click(function(){ if ($("#myTextField").val() != $(this).val()) alert("Field must match button text"); }); 实际上,服务器端和客户端没有任何区别。没错,这没有按钮点击操作,也没有向文本字段键入的操作,但在一个更高的层面上,事件正在 发生。一个连接被建立 — 事件!数据通过连接接收 — 事件!数据通过连接停止 — 事件! 为什么这种设置类型对 Node 很理想?JavaScript 是一种很棒的事件驱动编程语言,因为它允许匿名函数和闭包,更重要的是,任何写过代码的人都熟悉它的语法。事件发生时调用的回调函数可以在捕获事件处编写。这样,代码容易编写和维护,没有复杂的面向对象框架,没有接口,没有在上面架构任何内容的潜能。只需监听事件,编写一个回调函数,然后,事件驱动编程将照管好一切! 示例 Node 应用程序 最后,我们来看一些代码!让我们将讨论过的所有内容综合起来,创建我们的第一个 Node 应用程序。由于我们已经知道,Node 对于处理高流量应用程序很理想,我们就来创建一个非常简单的 web 应用程序 — 一个为实现最大速度而构建的应用程序。下面是 “老板” 交代的关于我们的样例应用程序的具体要求:创建一个随机数字生成器 RESTful API。这个应用程序应该接受一个输入:一个名为 “number” 的参数。然后,应用程序返回一个介于 0 和该参数之间的随机数字,并将生成的数字返回调用者。由于 “老板” 希望它成为一个广泛流行的应用程序,因此它应该能处理 50,000 个并发用户。我们来看看代码: 清单 2. Node 随机数字生成器 复制代码 代码如下: // these modules need to be imported in order to use them. // Node has several modules. They are like any #include // or import statement in other languages var http = require("http"); var url = require("url"); // The most important line in any Node file. This function // does the actual process of creating the server. Technically, // Node tells the underlying operating system that whenever a // connection is made, this particular callback function should be // executed. Since we're creating a web service with REST API, // we want an HTTP server, which requires the http variable // we created in the lines above. // Finally, you can see that the callback method receives a 'request' // and 'response' object automatically. This should be familiar // to any PHP or Java programmer. http.createServer(function(request, response) { // The response needs to handle all the headers, and the return codes // These types of things are handled automatically in server programs // like Apache and Tomcat, but Node requires everything to be done yourself response.writeHead(200, {"Content-Type": "text/plain"}); // Here is some unique-looking code. This is how Node retrives // parameters passed in from client requests. The url module // handles all these functions. The parse function // deconstructs the URL, and places the query key-values in the // query object. We can find the value for the "number" key // by referencing it directly - the beauty of JavaScript. var params = url.parse(request.url, true).query; var input = params.number; // These are the generic JavaScript methods that will create // our random number that gets passed back to the caller var numInput = new Number(input); var numOutput = new Number(Math.random() * numInput).toFixed(0); // Write the random number to response response.write(numOutput); // Node requires us to explicitly end this connection. This is because // Node allows you to keep a connection open and pass data back and forth, // though that advanced topic isn't discussed in this article. response.end(); // When we create the server, we have to explicitly connect the HTTP server to // a port. Standard HTTP port is 80, so we'll connect it to that one. }).listen(80); // Output a String to the console once the server starts up, letting us know everything // starts up correctly console.log("Random Number Generator Running..."); 将上面的代码放到一个名为 “random.js” 的文件中。现在,要启动这个应用程序并运行它(进而创建 HTTP 服务器并监听端口 80 上的连接),只需在您的命令提示中输入以下命令:% node random.js。下面是服务器已经启动并运行时它看起来的样子: 复制代码 代码如下: root@ubuntu:/home/moila/ws/mike# node random.js Random Number Generator Running... 访问应用程序 应用程序已经启动并运行。Node 正在监听任何连接,我们来测试一下。由于我们创建了一个简单的 RESTful API,我们可以使用我们的 web 浏览器来访问这个应用程序。键入以下地址(确保您完成了上面的步骤):localhost/?number=27。 您的浏览器窗口将更改到一个介于 0 到 27 之间的随机数字。单击浏览器上的 “重新载入” 按钮,将得到另一个随机数字。就是这样,这就是您的第一个 Node 应用程序! Node 对什么有好处? 到此为止,应该能够回答 “Node 是什么” 这个问题了,但您可能还不清楚什么时候应该使用它。这是一个需要提出的重要问题,因为 Node 对有一些东西有好处,但相反,对另一些东西而言,目前 Node 可能不是一个好的解决方案。您需要小心决定何时使用 Node,因为在错误的情况下使用它可能会导致一个多余编码的 LOT。 它对什么有好处? 正如您此前所看到的,Node 非常适合以下情况:您预计可能有很高的流量,而在响应客户端之前服务器端逻辑和处理所需不一定是巨大的。Node 表现出众的典型示例包括: 1.RESTful API 提供 RESTful API 的 web 服务接收几个参数,解析它们,组合一个响应,并返回一个响应(通常是较少的文本)给用户。这是适合 Node 的理想情况,因为您可以构建它来处理数万条连接。它还不需要大量逻辑;它只是从一个数据库查找一些值并组合一个响应。由于响应是少量文本,入站请求时少量文本,因此流量不高,一台机器甚至也可以处理最繁忙的公司的 API 需求。 2.Twitter 队列 想像一下像 Twitter 这样的公司,它必须接收 tweets 并将其写入一个数据库。实际上,每秒几乎有数千条 tweets 达到,数据库不可能及时处理高峰时段需要的写入数量。Node 成为这个问题的解决方案的重要一环。如您所见,Node 能处理数万条入站 tweets。它能迅速轻松地将它们写入一个内存排队机制(例如 memcached),另一个单独进程可以从那里将它们写入数据库。Node 在这里的角色是迅速收集 tweet 并将这个信息传递给另一个负责写入的进程。想象一下另一种设计 — 一个常规 PHP 服务器自己试图处理对数据库的写入 — 每个 tweet 将在写入数据库时导致一个短暂的延迟,这是因为数据库调用正在阻塞通道。由于数据库延迟,一台这样设计的机器每秒可能只能处理 2000 条入站 tweets。每秒 100 万条 tweets 需要 500 个服务器。相反,Node 能处理每个连接而不会阻塞通道,从而能捕获尽可能多的 tweets。一个能处理 50,000 条 tweets 的 Node 机器只需要 20 个服务器。 3.映像文件服务器 一个拥有大型分布式网站的公司(比如 Facebook 或 Flickr)可能会决定将所有机器只用于服务映像。Node 将是这个问题的一个不错的解决方案,因为该公司能使用它编写一个简单的文件检索器,然后处理数万条连接。Node 将查找映像文件,返回文件或一个 404 错误,然后什么也不用做。这种设置将允许这类分布式网站减少它们服务映像、.js 和 .css 文件等静态文件所需的服务器数量。 它对什么有坏处? 当然,在某些情况下,Node 并非理想选择。下面是 Node 不擅长的领域: 1.动态创建的页 目前,Node 没有提供一种默认方法来创建动态页。例如,使用 JavaServer Pages (JSP) 技术时,可以创建一个在这样的 JSP 代码段中包含循环的 index.jsp 页。Node 不支持这类动态的、HTML 驱动的页面。同样,Node 不太适合作为 Apache 和 Tomcat 这样的网页服务器。因此,如果您想在 Node 中提供这样一个服务器端解决方案,必须自己编写整个解决方案。PHP 程序员不想在每次部署 web 应用程序时都编写一个针对 Apache 的 PHP 转换器,当目前为止,这正是 Node 要求您做的。 2. 关系数据库重型应用程序 Node 的目的是快速、异步和非阻塞。数据库并不一定分享这些目标。它们是同步和阻塞的,因为读写时对数据库的调用在结果生成之前将一直阻塞通道。因此,一个每个请求都需要大量数据库调用、大量读取、大量写入的 web 应用程序非常不适合 Node,这是因为关系数据库本身就能抵销 Node 的众多优势。(新的 NoSQL 数据库更适合 Node,不过那完全是另一个主题了。) 结束语 问题是 “什么是 Node.js?” 应该已经得到解答。阅读本文之后,您应该能通过几个清晰简洁的句子回答这个问题。如果这样,那么您已经走到了许多编码员和程序员的前面。我和许多人都谈论过 Node,但它们对 Node 究竟是什么一直很迷惑。可以理解,他们具有的是 Apache 的思维方式 — 服务器是一个应用程序,将 HTML 文件放入其中,一切就会正常运转。而 Node 是目的驱动的。它是一个软件程序,使用 JavaScript 来允许程序员轻松快速地创建快速、可伸缩的 web 服务器。Apache 是运行就绪的,而 Node 是编码就绪的。 Node 完成了它提供高度可伸缩服务器的目标。它并不分配一个 “每个连接一个线程” 模型,而是使用一个 “每个连接一个流程” 模型,只创建每个连接需要的内存。它使用 Google 的一个非常快速的 JavaScript 引擎:V8 引擎。它使用一个事件驱动设计来保持代码最小且易于阅读。所有这些因素促成了 Node 的理想目标 — 编写一个高度可伸缩的解决方案变得比较容易。 与理解 Node 是 什么同样重要的是,理解它不是 什么。Node 并不是 Apache 的一个替代品,后者旨在使 PHP web 应用程序更容易伸缩。事实确实如此。在 Node 的这个初始阶段,大量程序员使用它的可能性不大,但在它能发挥作用的场景中,它的表现非常好。 将来应该期望从 Node 得到什么呢?这也许是本文引出的最重要的问题。既然您知道了它现在的作用,您应该会想知道它下一步将做什么。在接下来的一年中,我期待着 Node 提供与现有的第三方支持库更好地集成。现在,许多第三方程序员已经研发了用于 Node 的插件,包括添加文件服务器支持和 MySQL 支持。希望 Node 开始将它们集成到其核心功能中。最后,我还希望 Node 支持某种动态页面模块,这样,您就可以在 HTML 文件中执行在 PHP 和 JSP(也许是一个 NSP,一个 Node 服务器页)中所做的操作。最后,希望有一天会出现一个 “部署就绪” 的 Node 服务器,可以下载和安装,只需将您的 HTML 文件放到其中,就像使用 Apache 或 Tomcat 那样。Node 现在还处于初始阶段,但它发展得很快,可能不久就会出现在您的视野中。 答案来源于网络

养狐狸的猫 2019-12-02 02:17:03 0 浏览量 回答数 0

问题

PHP / MySQL中的地理搜索(距离)(性能)?mysql

保持可爱mmm 2020-05-17 11:58:48 2 浏览量 回答数 1

回答

*1、查询SQL尽量不要使用select ,而是select具体字段。 反例子: select * from employee; 正例子: select id,name from employee; 理由: 只取需要的字段,节省资源、减少网络开销。select * 进行查询时,很可能就不会使用到覆盖索引了,就会造成回表查询。 2、如果知道查询结果只有一条或者只要最大/最小一条记录,建议用limit 1 假设现在有employee员工表,要找出一个名字叫jay的人. CREATE TABLE `employee` ( `id` int(11) NOT NULL, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, `date` datetime DEFAULT NULL, `sex` int(1) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 反例: select id,name from employee where name='jay' 正例 select id,name from employee where name='jay' limit 1; 理由: 加上limit 1后,只要找到了对应的一条记录,就不会继续向下扫描了,效率将会大大提高。当然,如果name是唯一索引的话,是不必要加上limit 1了,因为limit的存在主要就是为了防止全表扫描,从而提高性能,如果一个语句本身可以预知不用全表扫描,有没有limit ,性能的差别并不大。 3、应尽量避免在where子句中使用or来连接条件 新建一个user表,它有一个普通索引userId,表结构如下: CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL, `age` int(11) NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), KEY `idx_userId` (`userId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 假设现在需要查询userid为1或者年龄为18岁的用户,很容易有以下sql 反例: select * from user where userid=1 or age =18 正例: //使用union all select * from user where userid=1 union all select * from user where age = 18 //或者分开两条sql写: select * from user where userid=1 select * from user where age = 18 理由: 使用or可能会使索引失效,从而全表扫描。 对于or+没有索引的age这种情况,假设它走了userId的索引,但是走到age查询条件时,它还得全表扫描,也就是需要三步过程: 全表扫描+索引扫描+合并 如果它一开始就走全表扫描,直接一遍扫描就完事。 mysql是有优化器的,处于效率与成本考虑,遇到or条件,索引可能失效,看起来也合情合理。 4、优化limit分页 我们日常做分页需求时,一般会用 limit 实现,但是当偏移量特别大的时候,查询效率就变得低下。 反例: select id,name,age from employee limit 10000,10 正例: //方案一 :返回上次查询的最大记录(偏移量) select id,name from employee where id>10000 limit 10. //方案二:order by + 索引 select id,name from employee order by id limit 10000,10 //方案三:在业务允许的情况下限制页数: 理由: 当偏移量最大的时候,查询效率就会越低,因为Mysql并非是跳过偏移量直接去取后面的数据,而是先把偏移量+要取的条数,然后再把前面偏移量这一段的数据抛弃掉再返回的。 如果使用优化方案一,返回上次最大查询记录(偏移量),这样可以跳过偏移量,效率提升不少。 方案二使用order by+索引,也是可以提高查询效率的。 方案三的话,建议跟业务讨论,有没有必要查这么后的分页啦。因为绝大多数用户都不会往后翻太多页。 5、优化你的like语句 日常开发中,如果用到模糊关键字查询,很容易想到like,但是like很可能让你的索引失效。 反例: select userId,name from user where userId like '%123'; 正例: select userId,name from user where userId like '123%'; 理由: 把%放前面,并不走索引,如下: 把% 放关键字后面,还是会走索引的。如下: 6、使用where条件限定要查询的数据,避免返回多余的行 假设业务场景是这样:查询某个用户是否是会员。曾经看过老的实现代码是这样。。。 反例: List<Long> userIds = sqlMap.queryList("select userId from user where isVip=1"); boolean isVip = userIds.contains(userId); 正例: Long userId = sqlMap.queryObject("select userId from user where userId='userId' and isVip='1' ") boolean isVip = userId!=null; 理由: 需要什么数据,就去查什么数据,避免返回不必要的数据,节省开销。 7、尽量避免在索引列上使用mysql的内置函数 业务需求:查询最近七天内登陆过的用户(假设loginTime加了索引) 反例: select userId,loginTime from loginuser where Date_ADD(loginTime,Interval 7 DAY) >=now(); 正例: explain select userId,loginTime from loginuser where loginTime >= Date_ADD(NOW(),INTERVAL - 7 DAY); 理由: 索引列上使用mysql的内置函数,索引失效 8、应尽量避免在 where 子句中对字段进行表达式操作,这将导致系统放弃使用索引而进行全表扫 反例: select * from user where age-1 =10; 正例: select * from user where age =11; 理由: 9、Inner join 、left join、right join,优先使用Inner join,如果是left join,左边表结果尽量小 Inner join 内连接,在两张表进行连接查询时,只保留两张表中完全匹配的结果集 left join 在两张表进行连接查询时,会返回左表所有的行,即使在右表中没有匹配的记录。 right join 在两张表进行连接查询时,会返回右表所有的行,即使在左表中没有匹配的记录。 都满足SQL需求的前提下,推荐优先使用Inner join(内连接),如果要使用left join,左边表数据结果尽量小,如果有条件的尽量放到左边处理。 反例: select * from tab1 t1 left join tab2 t2 on t1.size = t2.size where t1.id>2; 正例: select * from (select * from tab1 where id >2) t1 left join tab2 t2 on t1.size = t2.size; 理由: 如果inner join是等值连接,或许返回的行数比较少,所以性能相对会好一点。 同理,使用了左连接,左边表数据结果尽量小,条件尽量放到左边处理,意味着返回的行数可能比较少。 10、应尽量避免在 where 子句中使用!=或<>操作符,否则将引擎放弃使用索引而进行全表扫描。 反例: select age,name from user where age <>18; 正例: //可以考虑分开两条sql写 select age,name from user where age <18; select age,name from user where age >18; 理由: 使用!=和<>很可能会让索引失效 11、使用联合索引时,注意索引列的顺序,一般遵循最左匹配原则。 表结构:(有一个联合索引idx_userid_age,userId在前,age在后) CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `userId` int(11) NOT NULL, `age` int(11) DEFAULT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`), KEY `idx_userid_age` (`userId`,`age`) USING BTREE ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8; 反例: select * from user where age = 10; 正例: //符合最左匹配原则 select * from user where userid=10 and age =10; //符合最左匹配原则 select * from user where userid =10; 理由: 当我们创建一个联合索引的时候,如(k1,k2,k3),相当于创建了(k1)、(k1,k2)和(k1,k2,k3)三个索引,这就是最左匹配原则。 联合索引不满足最左原则,索引一般会失效,但是这个还跟Mysql优化器有关的。 12、对查询进行优化,应考虑在 where 及 order by 涉及的列上建立索引,尽量避免全表扫描。 反例: select * from user where address ='深圳' order by age ; 正例: 添加索引 alter table user add index idx_address_age (address,age) 13、如果插入数据过多,考虑批量插入。 反例: for(User u :list){ INSERT into user(name,age) values(#name#,#age#) } 正例: //一次500批量插入,分批进行 insert into user(name,age) values <foreach collection="list" item="item" index="index" separator=","> (#{item.name},#{item.age}) </foreach> 理由: 批量插入性能好,更加省时间 打个比喻:假如你需要搬一万块砖到楼顶,你有一个电梯,电梯一次可以放适量的砖(最多放500),你可以选择一次运送一块砖,也可以一次运送500,你觉得哪个时间消耗大? 14、在适当的时候,使用覆盖索引。 覆盖索引能够使得你的SQL语句不需要回表,仅仅访问索引就能够得到所有需要的数据,大大提高了查询效率。 反例: // like模糊查询,不走索引了 select * from user where userid like '%123%' 正例: //id为主键,那么为普通索引,即覆盖索引登场了。 select id,name from user where userid like '%123%'; 15、慎用distinct关键字 distinct 关键字一般用来过滤重复记录,以返回不重复的记录。在查询一个字段或者很少字段的情况下使用时,给查询带来优化效果。但是在字段很多的时候使用,却会大大降低查询效率。 反例: SELECT DISTINCT * from user; 正例: select DISTINCT name from user; 理由: 带distinct的语句cpu时间和占用时间都高于不带distinct的语句。因为当查询很多字段时,如果使用distinct,数据库引擎就会对数据进行比较,过滤掉重复数据,然而这个比较,过滤的过程会占用系统资源,cpu时间。 16、删除冗余和重复索引 反例: KEY `idx_userId` (`userId`) KEY `idx_userId_age` (`userId`,`age`) 正例: //删除userId索引,因为组合索引(A,B)相当于创建了(A)和(A,B)索引 KEY `idx_userId_age` (`userId`,`age`) 理由: 重复的索引需要维护,并且优化器在优化查询的时候也需要逐个地进行考虑,这会影响性能的。 17、如果数据量较大,优化你的修改/删除语句。 避免同时修改或删除过多数据,因为会造成cpu利用率过高,从而影响别人对数据库的访问。 反例: //一次删除10万或者100万+? delete from user where id <100000; //或者采用单一循环操作,效率低,时间漫长 for(User user:list){ delete from user; } 正例: //分批进行删除,如每次500 delete user where id<500 delete product where id>=500 and id<1000; 理由: 一次性删除太多数据,可能会有lock wait timeout exceed的错误,所以建议分批操作。 18、where子句中考虑使用默认值代替null。 反例: select * from user where age is not null; 正例: //设置0为默认值 select * from user where age>0; 理由: 并不是说使用了is null 或者 is not null 就会不走索引了,这个跟mysql版本以及查询成本都有关。 如果mysql优化器发现,走索引比不走索引成本还要高,肯定会放弃索引,这些条件!=,>is null,is not null经常被认为让索引失效,其实是因为一般情况下,查询的成本高,优化器自动放弃的。 如果把null值,换成默认值,很多时候让走索引成为可能,同时,表达意思会相对清晰一点。 19、不要有超过5个以上的表连接 连表越多,编译的时间和开销也就越大。 把连接表拆开成较小的几个执行,可读性更高。 如果一定需要连接很多表才能得到数据,那么意味着糟糕的设计了。 20、exist & in的合理利用 假设表A表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下SQL: select * from A where deptId in (select deptId from B); 这样写等价于: 先查询部门表B select deptId from B 再由部门deptId,查询A的员工 select * from A where A.deptId = B.deptId 可以抽象成这样的一个循环: List<> resultSet ; for(int i=0;i<B.length;i++) { for(int j=0;j<A.length;j++) { if(A[i].id==B[j].id) { resultSet.add(A[i]); break; } } } 显然,除了使用in,我们也可以用exists实现一样的查询功能,如下: select * from A where exists (select 1 from B where A.deptId = B.deptId); 因为exists查询的理解就是,先执行主查询,获得数据后,再放到子查询中做条件验证,根据验证结果(true或者false),来决定主查询的数据结果是否得意保留。 那么,这样写就等价于: select * from A,先从A表做循环 select * from B where A.deptId = B.deptId,再从B表做循环. 同理,可以抽象成这样一个循环: List<> resultSet ; for(int i=0;i<A.length;i++) { for(int j=0;j<B.length;j++) { if(A[i].deptId==B[j].deptId) { resultSet.add(A[i]); break; } } } 数据库最费劲的就是跟程序链接释放。假设链接了两次,每次做上百万次的数据集查询,查完就走,这样就只做了两次;相反建立了上百万次链接,申请链接释放反复重复,这样系统就受不了了。即mysql优化原则,就是小表驱动大表,小的数据集驱动大的数据集,从而让性能更优。 因此,我们要选择最外层循环小的,也就是,如果B的数据量小于A,适合使用in,如果B的数据量大于A,即适合选择exist。 21、尽量用 union all 替换 union 如果检索结果中不会有重复的记录,推荐union all 替换 union。 反例: select * from user where userid=1 union select * from user where age = 10 正例: select * from user where userid=1 union all select * from user where age = 10 理由: 如果使用union,不管检索结果有没有重复,都会尝试进行合并,然后在输出最终结果前进行排序。如果已知检索结果没有重复记录,使用union all 代替union,这样会提高效率。 22、索引不宜太多,一般5个以内。 索引并不是越多越好,索引虽然提高了查询的效率,但是也降低了插入和更新的效率。 insert或update时有可能会重建索引,所以建索引需要慎重考虑,视具体情况来定。 一个表的索引数最好不要超过5个,若太多需要考虑一些索引是否没有存在的必要。 23、尽量使用数字型字段,若只含数值信息的字段尽量不要设计为字符型 反例: king_id` varchar(20) NOT NULL COMMENT '守护者Id' 正例: `king_id` int(11) NOT NULL COMMENT '守护者Id'` 理由: 相对于数字型字段,字符型会降低查询和连接的性能,并会增加存储开销。 24、索引不适合建在有大量重复数据的字段上,如性别这类型数据库字段。 因为SQL优化器是根据表中数据量来进行查询优化的,如果索引列有大量重复数据,Mysql查询优化器推算发现不走索引的成本更低,很可能就放弃索引了。 25、尽量避免向客户端返回过多数据量。 假设业务需求是,用户请求查看自己最近一年观看过的直播数据。 反例: //一次性查询所有数据回来 select * from LivingInfo where watchId =useId and watchTime >= Date_sub(now(),Interval 1 Y) 正例: //分页查询 select * from LivingInfo where watchId =useId and watchTime>= Date_sub(now(),Interval 1 Y) limit offset,pageSize //如果是前端分页,可以先查询前两百条记录,因为一般用户应该也不会往下翻太多页, select * from LivingInfo where watchId =useId and watchTime>= Date_sub(now(),Interval 1 Y) limit 200 ; 26、当在SQL语句中连接多个表时,请使用表的别名,并把别名前缀于每一列上,这样语义更加清晰。 反例: select * from A inner join B on A.deptId = B.deptId; 正例: select memeber.name,deptment.deptName from A member inner join B deptment on member.deptId = deptment.deptId; 27、尽可能使用varchar/nvarchar 代替 char/nchar。 反例: `deptName` char(100) DEFAULT NULL COMMENT '部门名称' 正例: `deptName` varchar(100) DEFAULT NULL COMMENT '部门名称' 理由: 因为首先变长字段存储空间小,可以节省存储空间。 其次对于查询来说,在一个相对较小的字段内搜索,效率更高。 28、为了提高group by 语句的效率,可以在执行到该语句前,把不需要的记录过滤掉。 反例: select job,avg(salary) from employee group by job having job ='president' or job = 'managent' 正例: select job,avg(salary) from employee where job ='president' or job = 'managent' group by job; 29、如何字段类型是字符串,where时一定用引号括起来,否则索引失效 反例: select * from user where userid =123; 正例: select * from user where userid ='123'; 理由: 为什么第一条语句未加单引号就不走索引了呢? 这是因为不加单引号时,是字符串跟数字的比较,它们类型不匹配,MySQL会做隐式的类型转换,把它们转换为浮点数再做比较。 30、使用explain 分析你SQL的计划 日常开发写SQL的时候,尽量养成一个习惯吧。用explain分析一下你写的SQL,尤其是走不走索引这一块。 explain select * from user where userid =10086 or age =18;

剑曼红尘 2020-04-21 14:01:32 0 浏览量 回答数 0

问题

云数据库OceanBase的时间日期类型

云栖大讲堂 2019-12-01 21:28:35 1513 浏览量 回答数 0

回答

这里有一个关于此类问题的非常有趣的讨论: http://www.titov.net/2005/09/21/do-not-use-order-by-rand-or-how-to-get-random-rows-from-table/ 我认为在没有任何假设的情况下,您的O(n lg n)解决方案是最好的。尽管实际上使用好的优化程序或稍有不同的技术,但您列出的查询可能会更好一些,O(m * n)其中m是所需的随机行数,因为它不必对整个大型数组进行排序,它可能只搜索最小的m次。但是对于您发布的那种数字,无论如何,m大于lg n。 我们可以尝试以下三种假设: 表中有一个唯一的,已索引的主键 您要选择的随机行数(m)比表中的行数(n)小得多 唯一主键是一个整数,范围是1到n,没有空格 仅假设1和2,我认为这可以在O(n)中完成,尽管您需要向表中写入一个完整的索引以匹配假设3,因此不一定需要快速的O(n)。如果我们可以另外假设该表有其他优点,则可以在O(m log m)中执行任务。假设3是一个易于使用的好属性。有了一个很好的随机数生成器,它可以保证在连续生成m个数时不会重复,因此O(m)解决方案是可能的。 给定这三个假设,基本思想是生成介于1和n之间的m个唯一的随机数,然后从表中选择具有这些键的行。我现在没有mysql或任何更新,所以在伪代码中看起来像这样: create table RandomKeys (RandomKey int) create table RandomKeysAttempt (RandomKey int) -- generate m random keys between 1 and n for i = 1 to m insert RandomKeysAttempt select rand()*n + 1 -- eliminate duplicates insert RandomKeys select distinct RandomKey from RandomKeysAttempt -- as long as we don't have enough, keep generating new keys, -- with luck (and m much less than n), this won't be necessary while count(RandomKeys) < m NextAttempt = rand()*n + 1 if not exists (select * from RandomKeys where RandomKey = NextAttempt) insert RandomKeys select NextAttempt -- get our random rows select * from RandomKeys r join table t ON r.RandomKey = t.UniqueKey 如果您真的担心效率,则可以考虑使用某种过程语言来生成随机密钥,并将结果插入数据库中,因为除SQL以外,几乎任何其他方法都可能在所需的循环和随机数生成方面更好。

保持可爱mmm 2019-12-02 03:17:25 0 浏览量 回答数 0

问题

oracle的nvarchar2类型常见问题

oracledbawyq 2019-12-01 21:16:56 3225 浏览量 回答数 0

回答

当我可以在60秒内在类似硬件上执行相同操作时,您的查询要花2个小时才能执行,这是一件非常错误的事情。 以下某些内容可能会有所帮助... 为您的引擎调整MySQL 检查服务器配置并进行相应优化。以下某些资源应该是有用的。 http://www.mysqlperformanceblog.com/2006/09/29/what-to-tune-in-mysql-server-after-installation/ http://www.mysqlperformanceblog.com/ http://www.highperfmysql.com/ http://forge.mysql.com/wiki/ServerVariables http://dev.mysql.com/doc/refman/5.0/en/server-system-variables.html http://www.xaprb.com/blog/2006/07/04/how-to-exploit-mysql-index-optimizations/ http://jpipes.com/presentations/perf_tuning_best_practices.pdf http://jpipes.com/presentations/index_coding_optimization.pdf http://www.jasny.net/?p=36 现在不那么明显了... 考虑使用存储过程来处理数据服务器端 为什么不处理MySQL内部的所有数据,从而不必将大量数据发送到应用程序层?以下示例使用游标在2分钟内循环和处理服务器端5000万行。我不是游标的忠实拥护者,尤其是在MySQL游标非常有限的地方,但是我猜想您会循环结果集并进行某种形式的数值分析,因此在这种情况下使用游标是合理的。 简化的myisam结果表-基于您的密钥。 drop table if exists results_1mregr_c_ew_f; create table results_1mregr_c_ew_f ( id int unsigned not null auto_increment primary key, rc tinyint unsigned not null, df int unsigned not null default 0, val double(10,4) not null default 0, ts timestamp not null default now(), key (rc, df) ) engine=myisam; 我生成了1亿行数据,其中关键字段的基数与您的示例大致相同: show indexes from results_1mregr_c_ew_f; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Index_type ===== ========== ======== ============ =========== ========= =========== ========== results_1mregr_c_ew_f 0 PRIMARY 1 id A 100000000 BTREE results_1mregr_c_ew_f 1 rc 1 rc A 2 BTREE results_1mregr_c_ew_f 1 rc 2 df A 223 BTREE 存储过程 我创建了一个简单的存储过程,该过程将获取所需的数据并对其进行处理(使用与示例相同的where条件) drop procedure if exists process_results_1mregr_c_ew_f; delimiter # create procedure process_results_1mregr_c_ew_f ( in p_rc tinyint unsigned, in p_df int unsigned ) begin declare v_count int unsigned default 0; declare v_done tinyint default 0; declare v_id int unsigned; declare v_result_cur cursor for select id from results_1mregr_c_ew_f where rc = p_rc and df > p_df; declare continue handler for not found set v_done = 1; open v_result_cur; repeat fetch v_result_cur into v_id; set v_count = v_count + 1; -- do work... until v_done end repeat; close v_result_cur; select v_count as counter; end # delimiter ; 观察到以下运行时: call process_results_1mregr_c_ew_f(0,60); runtime 1 = 03:24.999 Query OK (3 mins 25 secs) runtime 2 = 03:32.196 Query OK (3 mins 32 secs) call process_results_1mregr_c_ew_f(1,60); runtime 1 = 04:59.861 Query OK (4 mins 59 secs) runtime 2 = 04:41.814 Query OK (4 mins 41 secs) counter 23000002 (23 million rows processed in each case) 嗯,性能有些令人失望,因此进入下一个想法。 考虑使用innodb引擎(令人震惊的恐怖) 为什么是innodb?因为它具有聚簇索引!您会发现使用innodb的插入速度较慢,但​​希望读取速度会更快,因此这是值得的折衷选择。 通过聚集索引访问行的速度很快,因为行数据位于索引搜索所位于的同一页上。如果表很大,则与使用不同于索引记录的页面存储行数据的存储组织相比,聚集索引体系结构通常可以节省磁盘I / O操作。例如,MyISAM将一个文件用于数据行,将另一个文件用于索引记录。 更多信息在这里: http://dev.mysql.com/doc/refman/5.0/en/innodb-index-types.html 简化的innodb结果表 drop table if exists results_innodb; create table results_innodb ( rc tinyint unsigned not null, df int unsigned not null default 0, id int unsigned not null, -- cant auto_inc this !! val double(10,4) not null default 0, ts timestamp not null default now(), primary key (rc, df, id) -- note clustered (innodb only !) composite PK ) engine=innodb; innodb的一个问题是它不支持构成复合键一部分的auto_increment字段,因此您必须自己使用序列生成器,触发器或其他方法(可能是在填充结果表本身的应用程序中)提供递增的键值?? 同样,我生成了1亿行数据,这些键字段的基数与您的示例大致相同。如果这些数字与myisam示例不匹配,请不要担心,因为innodb估计基数,因此它们不会完全相同。(但它们-使用相同的数据集) show indexes from results_innodb; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Index_type ===== ========== ======== ============ =========== ========= =========== ========== results_innodb 0 PRIMARY 1 rc A 18 BTREE results_innodb 0 PRIMARY 2 df A 18 BTREE results_innodb 0 PRIMARY 3 id A 100000294 BTREE 存储过程 存储过程与上面的myisam示例完全相同,但是从innodb表中选择数据。 declare v_result_cur cursor for select id from results_innodb where rc = p_rc and df > p_df; 结果如下: call process_results_innodb(0,60); runtime 1 = 01:53.407 Query OK (1 mins 53 secs) runtime 2 = 01:52.088 Query OK (1 mins 52 secs) call process_results_innodb(1,60); runtime 1 = 02:01.201 Query OK (2 mins 01 secs) runtime 2 = 01:49.737 Query OK (1 mins 50 secs) counter 23000002 (23 million rows processed in each case) 比myisam引擎实施快约2-3分钟!(innodb FTW) 分而治之 在使用游标的服务器端存储过程中处理结果可能不是最佳解决方案,尤其是因为MySQL不支持诸如数组和复杂数据结构之类的东西,而这些东西在3GL语言(如C#等)或什至在其他数据库(如作为Oracle PL / SQL。 因此,这里的想法是将成批的数据返回到应用程序层(C#等),然后可以将结果添加到基于集合的数据结构中,然后在内部处理数据。 存储过程 该存储过程需要3个参数rc,df_low和df_high,这使您可以选择以下数据范围: call list_results_innodb(0,1,1); -- df 1 call list_results_innodb(0,1,10); -- df between 1 and 10 call list_results_innodb(0,60,120); -- df between 60 and 120 etc... 显然,df范围越高,您将提取的数据越多。 drop procedure if exists list_results_innodb; delimiter # create procedure list_results_innodb ( in p_rc tinyint unsigned, in p_df_low int unsigned, in p_df_high int unsigned ) begin select rc, df, id from results_innodb where rc = p_rc and df between p_df_low and p_df_high; end # delimiter ; 我还敲出了一个myisam版本,除了所使用的表外,该版本完全相同。 call list_results_1mregr_c_ew_f(0,1,1); call list_results_1mregr_c_ew_f(0,1,10); call list_results_1mregr_c_ew_f(0,60,120); 基于上面的光标示例,我希望innodb版本的性能优于myisam版本。 我开发了一个快速且肮脏的多线程C#应用程序,该应用程序将调用存储过程并将结果添加到集合中以进行后查询处理。您不必使用线程,可以按顺序完成相同的批处理查询方法,而不会造成性能损失。 每个线程(QueryThread)选择一个df数据范围,循环结果集,并将每个结果(行)添加到结果集合中。 class Program { static void Main(string[] args) { const int MAX_THREADS = 12; const int MAX_RC = 120; List<AutoResetEvent> signals = new List<AutoResetEvent>(); ResultDictionary results = new ResultDictionary(); // thread safe collection DateTime startTime = DateTime.Now; int step = (int)Math.Ceiling((double)MAX_RC / MAX_THREADS) -1; int start = 1, end = 0; for (int i = 0; i < MAX_THREADS; i++){ end = (i == MAX_THREADS - 1) ? MAX_RC : end + step; signals.Add(new AutoResetEvent(false)); QueryThread st = new QueryThread(i,signals[i],results,0,start,end); start = end + 1; } WaitHandle.WaitAll(signals.ToArray()); TimeSpan runTime = DateTime.Now - startTime; Console.WriteLine("{0} results fetched and looped in {1} secs\nPress any key", results.Count, runTime.ToString()); Console.ReadKey(); } } 运行时观察如下: Thread 04 done - 31580517 Thread 06 done - 44313475 Thread 07 done - 45776055 Thread 03 done - 46292196 Thread 00 done - 47008566 Thread 10 done - 47910554 Thread 02 done - 48194632 Thread 09 done - 48201782 Thread 05 done - 48253744 Thread 08 done - 48332639 Thread 01 done - 48496235 Thread 11 done - 50000000 50000000 results fetched and looped in 00:00:55.5731786 secs Press any key 因此,在不到60秒的时间内获取了5000万行并将其添加到集合中。 我使用myisam存储过程尝试了同样的事情,该过程花了2分钟才能完成。 50000000 results fetched and looped in 00:01:59.2144880 secs 移至innodb 在我的简化系统中,myisam表的性能不会太差,因此可能不值得迁移到innodb。如果您确实决定将结果数据复制到innodb表中,请按照以下步骤进行操作: start transaction; insert into results_innodb select <fields...> from results_1mregr_c_ew_f order by ; commit; 在将整个事物插入并包装到事务中之前,通过innodb PK对结果进行排序将加快速度。 我希望其中一些证明是有帮助的。 祝好运

保持可爱mmm 2020-05-18 11:14:35 0 浏览量 回答数 0

回答

我想很多朋友会发现自己的mysql占用一大量的内在与cpu了,解决这个问题我们大多会直接减少mysql访问与连接次数,直接生成静态或缓存文件,下面我还有更多办法来解决mysql占高CPU与内存的办法。 为了装mysql环境测试,装上后发现启动后MySQL占用内存了很大,达8百多兆。网上搜索了一下,得到高人指点my.ini。再也没见再详细的了..只好打开my.ini逐行的啃,虽然英文差了点,不过多少M还是看得明的^-^更改后如下:innodb_buffer_pool_size=576M ->256M InnoDB引擎缓冲区占了大头,首要就是拿它开刀query_cache_size=100M ->16M 查询缓存tmp_table_size=102M ->64M 临时表大小key_buffer_size=256m ->32M重启mysql服务后,虚拟内存降到200以下.另外mysql安装目录下有几个文件:my-huge.ini 、my-large.ini、my-medium.ini...这几个是根据内存大小作的建议配置,新手在设置的时候也可以参考一下。2G内存的MYSQL数据库服务器 my.ini优化 (my.ini)2G内存,针对站少,优质型的设置,试验特:table_cache=1024 物理内存越大,设置就越大.默认为2402,调到512-1024最佳innodb_additional_mem_pool_size=8M 默认为2Minnodb_flush_log_at_trx_commit=0 等到innodb_log_buffer_size列队满后再统一储存,默认为1innodb_log_buffer_size=4M 默认为1Minnodb_thread_concurrency=8 你的服务器CPU有几个就设置为几,默认为8key_buffer_size=256M 默认为218 调到128最佳tmp_table_size=64M 默认为16M 调到64-256最挂read_buffer_size=4M 默认为64Kread_rnd_buffer_size=16M 默认为256Ksort_buffer_size=32M 默认为256Kmax_connections=1024 默认为1210试验一:table_cache=512或1024innodb_additional_mem_pool_size=2Minnodb_flush_log_at_trx_commit=0innodb_log_buffer_size=1Minnodb_thread_concurrency=8 你的服务器CPU有几个就设置为几,默认为8key_buffer_size=128Mtmp_table_size=128Mread_buffer_size=64K或128Kread_rnd_buffer_size=256Ksort_buffer_size=512Kmax_connections=1024试验二:table_cache=512或1024innodb_additional_mem_pool_size=8Minnodb_flush_log_at_trx_commit=0innodb_log_buffer_size=4Minnodb_thread_concurrency=8key_buffer_size=128Mtmp_table_size=128Mread_buffer_size=4Mread_rnd_buffer_size=16Msort_buffer_size=32Mmax_connections=1024一般:table_cache=512innodb_additional_mem_pool_size=8Minnodb_flush_log_at_trx_commit=0innodb_log_buffer_size=4Minnodb_thread_concurrency=8key_buffer_size=128Mtmp_table_size=128Mread_buffer_size=4Mread_rnd_buffer_size=16Msort_buffer_size=32Mmax_connections=1024经过测试.没有特殊情况,最好还是用默认的.2G内存,针对站多,抗压型的设置,最佳:table_cache=1024 物理内存越大,设置就越大.默认为2402,调到512-1024最佳innodb_additional_mem_pool_size=4M 默认为2Minnodb_flush_log_at_trx_commit=1(设置为0就是等到innodb_log_buffer_size列队满后再统一储存,默认为1)innodb_log_buffer_size=2M 默认为1Minnodb_thread_concurrency=8 你的服务器CPU有几个就设置为几,建议用默认一般为8key_buffer_size=256M 默认为218 调到128最佳tmp_table_size=64M 默认为16M 调到64-256最挂read_buffer_size=4M 默认为64Kread_rnd_buffer_size=16M 默认为256Ksort_buffer_size=32M 默认为256Kmax_connections=1024 默认为1210thread_cache_size=120 默认为60query_cache_size=64M优化mysql数据库性能的十个参数(1)、max_connections:允许的同时客户的数量。增加该值增加 mysqld 要求的文件描述符的数量。这个数字应该增加,否则,你将经常看到 too many connections 错误。 默认数值是100,我把它改为1024 。(2)、record_buffer:每个进行一个顺序扫描的线程为其扫描的每张表分配这个大小的一个缓冲区。如果你做很多顺序扫描,你可能想要增加该值。默认数值是131072(128k),我把它改为16773120 (16m)(3)、key_buffer_size:索引块是缓冲的并且被所有的线程共享。key_buffer_size是用于索引块的缓冲区大小,增加它可得到更好处理的索引(对所有读和多重写),到你 能负担得起那样多。如果你使它太大,系统将开始换页并且真的变慢了。默认数值是8388600(8m),我的mysql主机有2gb内存,所以我把它改为 402649088(400mb)。4)、back_log:要求 mysql 能有的连接数量。当主要mysql线程在一个很短时间内得到非常多的连接请求,这就起作用,然后主线程花些时间(尽管很短)检查连接并且启动一个新线程。back_log 值指出在mysql暂时停止回答新请求之前的短时间内多少个请求可以被存在堆栈中。只有如果期望在一个短时间内有很多连接,你需要增加它,换句话说,这值 对到来的tcp/ip连接的侦听队列的大小。你的操作系统在这个队列大小上有它自己的限制。试图设定back_log高于你的操作系统的限制将是无效的。当你观察你的主机进程列表,发现大量 264084 | unauthenticated user | xxx.xxx.xxx.xxx | null | connect | null | login | null 的待连接进程时,就要加大 back_log 的值了。默认数值是50,我把它改为500。(5)、interactive_timeout:服务器在关闭它前在一个交互连接上等待行动的秒数。一个交互的客户被定义为对 mysql_real_connect()使用 client_interactive 选项的客户。 默认数值是28800,我把它改为7200。(6)、sort_buffer:每个需要进行排序的线程分配该大小的一个缓冲区。增加这值加速order by或group by操作。默认数值是2097144(2m),我把它改为 16777208 (16m)。(7)、table_cache:为所有线程打开表的数量。增加该值能增加mysqld要求的文件描述符的数量。mysql对每个唯一打开的表需要2个文件描述符。默认数值是64,我把它改为512。(8)、thread_cache_size:可以复用的保存在中的线程的数量。如果有,新的线程从缓存中取得,当断开连接的时候如果有空间,客户的线置在缓存中。如果有很多新的线程,为了提高性能可 以这个变量值。通过比较 connections 和 threads_created 状态的变量,可以看到这个变量的作用。我把它设置为 80。(9)mysql的搜索功能用mysql进行搜索,目的是能不分大小写,又能用中文进行搜索只需起动mysqld时指定 --default-character-set=gb2312(10)、wait_timeout:服务器在关闭它之前在一个连接上等待行动的秒数。 默认数值是28800,我把它改为7200。注:参数的调整可以通过修改 /etc/my.cnf 文件并重启 mysql 实现。这是一个比较谨慎的工作,上面的结果也仅仅是我的一些看法,你可以根据你自己主机的硬件情况(特别是内存大小)进一步修改。

我的中国 2019-12-02 01:33:22 0 浏览量 回答数 0

问题

MySQL 数据类型,数据库报错

python小菜菜 2020-06-01 16:05:21 1 浏览量 回答数 1

回答

HI,要搞清楚锁,首先要搞清楚,PG是有很多可以加锁的对象的,每种对象下面,再去看它的锁冲突。 可以加锁的对象: LOCKTAG_RELATION, /* whole relation */ /* ID info for a relation is DB OID + REL OID; DB OID = 0 if shared */ LOCKTAG_RELATION_EXTEND, /* the right to extend a relation */ /* same ID info as RELATION */ LOCKTAG_PAGE, /* one page of a relation */ /* ID info for a page is RELATION info + BlockNumber */ LOCKTAG_TUPLE, /* one physical tuple */ /* ID info for a tuple is PAGE info + OffsetNumber */ LOCKTAG_TRANSACTION, /* transaction (for waiting for xact done) */ /* ID info for a transaction is its TransactionId */ LOCKTAG_VIRTUALTRANSACTION, /* virtual transaction (ditto) */ /* ID info for a virtual transaction is its VirtualTransactionId */ LOCKTAG_SPECULATIVE_TOKEN, /* speculative insertion Xid and token */ /* ID info for a transaction is its TransactionId */ LOCKTAG_OBJECT, /* non-relation database object */ /* ID info for an object is DB OID + CLASS OID + OBJECT OID + SUBID */ /* * Note: object ID has same representation as in pg_depend and * pg_description, but notice that we are constraining SUBID to 16 bits. * Also, we use DB OID = 0 for shared objects such as tablespaces. */ LOCKTAG_USERLOCK, /* reserved for old contrib/userlock code */ LOCKTAG_ADVISORY /* advisory user locks */ 锁模式 /* NoLock is not a lock mode, but a flag value meaning "don't get a lock" */ #define NoLock 0 #define AccessShareLock 1 /* SELECT */ #define RowShareLock 2 /* SELECT FOR UPDATE/FOR SHARE */ #define RowExclusiveLock 3 /* INSERT, UPDATE, DELETE */ #define ShareUpdateExclusiveLock 4 /* VACUUM (non-FULL),ANALYZE, CREATE * INDEX CONCURRENTLY */ #define ShareLock 5 /* CREATE INDEX (WITHOUT CONCURRENTLY) */ #define ShareRowExclusiveLock 6 /* like EXCLUSIVE MODE, but allows ROW * SHARE */ #define ExclusiveLock 7 /* blocks ROW SHARE/SELECT...FOR * UPDATE */ #define AccessExclusiveLock 8 /* ALTER TABLE, DROP TABLE, VACUUM * FULL, and unqualified LOCK TABLE */ 然后我们说一下死锁,死锁相互等待造成的,你给的图没有等待,所以一定不是死锁。 最后提供一个查询锁和等待的方法给你,会比较好看。 用一个函数来将锁转换为数字, postgres=# create or replace function f_lock_level(i_mode text) returns int as $$ declare begin case i_mode when 'INVALID' then return 0; when 'AccessShareLock' then return 1; when 'RowShareLock' then return 2; when 'RowExclusiveLock' then return 3; when 'ShareUpdateExclusiveLock' then return 4; when 'ShareLock' then return 5; when 'ShareRowExclusiveLock' then return 6; when 'ExclusiveLock' then return 7; when 'AccessExclusiveLock' then return 8; else return 0; end case; end; $$ language plpgsql strict; 修改查询语句,按锁级别排序: with t_wait as (select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.objid,a.objsubid, a.pid,a.virtualtransaction,a.virtualxid,a,transactionid,b.query,b.xact_start,b.query_start, b.usename,b.datname from pg_locks a,pg_stat_activity b where a.pid=b.pid and not a.granted), t_run as (select a.mode,a.locktype,a.database,a.relation,a.page,a.tuple,a.classid,a.objid,a.objsubid, a.pid,a.virtualtransaction,a.virtualxid,a,transactionid,b.query,b.xact_start,b.query_start, b.usename,b.datname from pg_locks a,pg_stat_activity b where a.pid=b.pid and a.granted) select r.locktype,r.mode r_mode,r.usename r_user,r.datname r_db,r.relation::regclass,r.pid r_pid, r.page r_page,r.tuple r_tuple,r.xact_start r_xact_start,r.query_start r_query_start, now()-r.query_start r_locktime,r.query r_query,w.mode w_mode,w.pid w_pid,w.page w_page, w.tuple w_tuple,w.xact_start w_xact_start,w.query_start w_query_start, now()-w.query_start w_locktime,w.query w_query from t_wait w,t_run r where r.locktype is not distinct from w.locktype and r.database is not distinct from w.database and r.relation is not distinct from w.relation and r.page is not distinct from w.page and r.tuple is not distinct from w.tuple and r.classid is not distinct from w.classid and r.objid is not distinct from w.objid and r.objsubid is not distinct from w.objsubid and r.transactionid is not distinct from w.transactionid and r.pid <> w.pid order by f_lock_level(w.mode)+f_lock_level(r.mode) desc,r.xact_start; 现在可以排在前面的就是锁级别高的等待,优先干掉这个。 -[ RECORD 1 ]-+--------------------------------------------------------------------- locktype | relation -- 冲突类型 r_mode | ShareUpdateExclusiveLock -- 持锁模式 r_user | postgres -- 持锁用户 r_db | postgres -- 持锁数据库 relation | tbl -- 持锁对象 r_pid | 25656 -- 持锁进程 r_xact_start | 2015-05-10 14:11:16.08318+08 -- 持锁事务开始时间 r_query_start | 2015-05-10 14:11:16.08318+08 -- 持锁SQL开始时间 r_locktime | 00:01:49.460779 -- 持锁时长 r_query | vacuum freeze tbl; -- 持锁SQL,注意不一定是这个SQL带来的锁,也有可能是这个事务在之前执行的SQL加的锁 w_mode | AccessExclusiveLock -- 等待锁模式 w_pid | 26731 -- 等待锁进程 w_xact_start | 2015-05-10 14:11:17.987362+08 -- 等待锁事务开始时间 w_query_start | 2015-05-10 14:11:17.987362+08 -- 等待锁SQL开始时间 w_locktime | 00:01:47.556597 -- 等待锁时长 w_query | truncate tbl; -- 等待锁SQL -[ RECORD 2 ]-+--------------------------------------------------------------------- locktype | relation r_mode | ShareUpdateExclusiveLock r_user | postgres r_db | postgres relation | tbl r_pid | 25656 r_xact_start | 2015-05-10 14:11:16.08318+08 r_query_start | 2015-05-10 14:11:16.08318+08 r_locktime | 00:01:49.460779 r_query | vacuum freeze tbl; w_mode | RowExclusiveLock w_pid | 25582 w_xact_start | 2015-05-10 14:11:22.845+08 w_query_start | 2015-05-10 14:11:22.845+08 w_locktime | 00:01:42.698959 w_query | insert into tbl(crt_time) select now() from generate_series(1,1000); -- 这个SQL其实等待的是truncate tbl的锁; ......

德哥 2019-12-02 01:29:55 0 浏览量 回答数 0

回答

---数据库版本 select * from v$version ---SCOTT默认表空间以及用户 select u.username,u.default_tablespace from dba_users u where u.username='SCOTT' select * from database_properties dp where dp.property_name='DEFAULT_PERMANENT_TABLESPACE'; select u.username,u.default_tablespace from dba_users u where u.username='dborcl' select * from dba_tablespaces ---1.首先,创建(新)用户: create user gaohao identified by gaohao; --也可以不创建新用户,而仍然用以前的用户,如:继续利用scott用户 ---2.创建表空间: create tablespace ZTTM datafile 'd:\oracle\data.dbf' size 500M; ---3.将空间分配给用户: alter user gaohao default tablespace ZTTM; ---将名字为tablespacename的表空间分配给username ---4.给用户授权: grant create session,create table,unlimited tablespace to gaohao; ---5.然后再以楼主自己创建的用户登录,登录之后创建表即可。 create user ZTTM identified by zttm; alter user ZTTM default tablespace ZTTM; grant create session,create table,unlimited tablespace to ZTTM; ---建表 create table UserInfo ( USERID int primary key , UNAME varchar(20) not null, ISMARRAY char(5) not null, ISONJOB char(5) not null, REMARK varchar(500) null ) insert into UserInfo values(1,'Tom','0','0','*****************************'); insert into UserInfo values(2,'JACK','1','0','JJJJJJJJJJJJJJJJJJJJJJJJJ'); insert into UserInfo values(3,'JIM','0','1','WWWWWWWWWWWWWWW'); insert into UserInfo values(4,'BOT','1','1','AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'); insert into UserInfo values(5,'KATE','1','0','GGGGGGGGGGGGGGGGGGGGGGGG'); insert into UserInfo values(6,'BRAN','0','1','HHHHHHHHHHHHHHHHHHHHHHHHHHHHH'); insert into UserInfo values(7,'JUN','1','1','RRRRRRRRRRRRRRRRRRRRRRRRRRR'); insert into UserInfo values(8,'ANDRUE','1','1','EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE'); insert into UserInfo values(9,'ALICE','1','0','VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV'); insert into UserInfo values(10,'HANKS','0','1','QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ'); insert into UserInfo values(11,'KEBE','0','1','BNNNNNNNNNNNNNNNNNNNNNNNN'); insert into UserInfo values(12,'SAM','1','0','ZXXXXXXXXXXXXXXXXXXXXXXXXXXXX'); insert into UserInfo values(13,'BOB','0','0','TTTTTTTTTTTTTTTTTTTTTTTTTTTT'); select * from UserInfo; select to_date('20120725115536','yyyy-MM-dd HH24:mi:ss') TimeStamp from dual grant select on v_$statname to gaohao; grant select on v_$session to gaohao; grant select on v_$sesstat to gaohao; grant select on v_$mystat to gaohao; grant select on v_$statname to ZTTM; grant select on v_$session to ZTTM; grant select on v_$sesstat to ZTTM; grant select on v_$mystat to ZTTM; select u.USERID,--员工编号 u.UNAME, --员工姓名 u.ISMARRAY, --婚否 u.ISONJOB,--是否在职 u.REMARK --备注 from UserInfo u where u.USERID like '%1%' select to_char(to_date('20120727094755','yyyy-mm-dd hh24:mi:ss'),'yyyy-mm-dd hh24:mi:ss') CurrentTime from dual select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') CurrentTime from dual; select TO_DATE(null) from dual; /SQL语句/ select * from log_cpuidle where idle_date = (select to_char(sysdate-1,'DD-MON-YY') from dual); /*其中idle_date是DATE类型的,不知道为啥要将sysdate进行转换,只有这样才能查找到日期是前一天的数据; 其中要注意的是sysdate对应的格式为DD-MON-YY;*/ insert into table select a, b, count()c,avg(d),e from LOG_TABLE where a=(select to_char(sysdate-1, 'DD-MON-YY') from dual) group by a, b, e order by b; / 复合型的insert 语句; 取前几行的数据用rownum;select * from table where rownum < 10; group by:分组查询,一般和聚合函数(AVG、SUM、MAX、COUNT等)一起使用,它后面可以跟having限制性语句; order by:select “栏位名” from “表格”[where “条件”] order by “栏位名”[asc, desc]*/ •/============创建Customer表==========/ •create table Customer •( • Customer_id number(6) not null, • Customer_name varchar2(50) not null, • Password varchar2(20) not null, • True_name varchar2(20), • Email_address varchar2(50) not null, --唯一 • Password_question varchar2(50) not null, • Password_anwser varchar2(50) not null, • Status char(1), --默认是1,取值0或1 • Customer_level char(1), --默认是1,取值1,2,3 • Score number(6), • Register_date date, --默认为系统时间 • Login_time timestamp, • Login_count number(6), • Login_ip char(6) •); •/===========创建Orders表==========/ •create table Orders •( • Order_id varchar2(10) not null, • Order_Customer_id number(6) not null, • Order_date date not null, • Order_price number not null •); •/==========查询Customer表===========/ •select * from Customer • •/==========向表中添加数据===========/ •insert into Customer values •(220077,'wantingqiang','wtq','万廷强','lovezhqj@qq.com','你是哪个?','wtq','1','3',150,sysdate,sysdate,15789,'172.26') • •/==========修改表Customer===========/ •alter table Customer •modify Login_ip char(16); • •/=========修改第一条记录中的ip=====/ •update Customer set Login_ip='172.26.3.145' where Customer_id='220077';--ip地址修改成功 • •/=========添加一个列===============/ •alter table Customer •add LoginOut_time date; --新列增加成功 • •/=========删除一个列LoginOut_time========/ •alter table Customer •drop column LoginOut_time; --列删除成功 • •/========给列添加注释===========/ •comment on column • Customer.Customer_Name is '客户姓名'; • •/========给表添加注释==========/ •comment on table Customer is '客户表,为了保持与客户的联系'; • •/========重新命名表============/ •alter table Customer rename to Customer_Change; • •select * from Customer_Change • •alter table Customer_Change rename to Customer; • •/==========添加非空约束========/ •alter table Customer •modify status not null; --非空约束添加成功 • •/==========添加主键约束========/ •alter table Customer •add constraint customer_id_pk primary key(Customer_id); --主键添加成功 • •/==========添加外键约束========/ •--向Orders表中添加外键,与Customer表关联 •--在下面的列子末尾加上: •--on delete 表示允许级联删除 •--on update 表示允许级联更新 •alter table Orders •add constraint Orders_Customer_fk foreign key(Order_Customer_id) references Customer(Customer_id); •--外键添加成功 •/==========删除外键约束=========/ •alter table Orders •drop constraint "ORDERS_CUSTOMER_FK"; --外键删除成功,这个要注意大小写哈 • •/=========添加唯一约束========/ •alter table Customer •add constraint un_email unique(Email_address); --添加唯一约束成功 • • •/=========修改默认约束========/ •alter table Customer •modify Status default('1'); • •/=========添加检查约束========/ •alter table Customer •add constraint ck_status check(Status in ('1','0')); --检查约束添加成功 • • •/==========禁止检查约束=======/ •alter table Customer • disable constraint ck_status; --禁止成功 • •/==========激活检查约束=======/ •alter table Customer • enable constraint ck_status; --激活成功 • •/==========删除检查约束========/ •alter table Customer •drop constraint ck_status; --删除检查约束成功 • •/==========最后是删除表========/ •drop table Customer; --删除表成功 /使用SQLPLUS(1) SQL> desc table; 显示表结构 SQL> select * from tab; 查看用户下所有的表 SQL> set pause on; 可以使大量结果集在用户按“Enter”(回车)后翻页 SQL> set pagesize 100; 设定SQL语句返回结果集一页的行数100, 默认值是14 SQL> set linesize 100; 设定SQL语句返回结果集一行的宽度100, 默认值是80*/ /*常用的日期处理函数 oracle内部以数字格式存储日期和时间信息:世纪,年,月,日,小时,分钟,秒 临时表dual表 缺省格式:DD-MON-YY('14-3月-08') round(to_date('14-3月-08'),'month') 可使用sysdate函数(没有参数和括号)获取当前系统日期和时间 日期数据直接加或减一个数值(不一定是整数,代表的是多少天),结果仍为日期(约定的单位为天,当然也可以为月或年) 两个日期数据可以相减(不可相加,没有意义 ),结果为二者相差多少天 add_months(日期x,数值y):计算在日期x基础上增加y个月后的日期 add_months(sysdate,2) last_day(s) 返回日期x当月最后一天的日期 last_day(sysdate) months_between(x,y) 返回日期x和y之间相差的月数 months_between(sysdate,sysdate) 有正负号之分(参数前后关系有关) round(x,y) 四舍五入将日期x截断到y所指定的日期单位(月或年)的第一天 round(sysdate,'month') 3月14号为3月1号 3月16号为4月1号 年的同理round(sysdate,'year') trunc(x,y) 将日期x截断到y所指定的日期单位(月或年)的第一天,不四舍五入trunc(sysdate,'month')trunc(sysdate,'year') next_day(x,y) 计算指定日期x后的第一个星期几(由参数y指定)对应的日期 next_day(sysdate,'星期二')*/ select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as nowTime from dual; //日期转化为字符串 select to_char(sysdate,'yyyy') as nowYear from dual; //获取时间的年 select to_char(sysdate,'mm') as nowMonth from dual; //获取时间的月 select to_char(sysdate,'dd') as nowDay from dual; //获取时间的日 select to_char(sysdate,'hh24') as nowHour from dual; //获取时间的时 select to_char(sysdate,'mi') as nowMinute from dual; //获取时间的分 select to_char(sysdate,'ss') as nowSecond from dual; //获取时间的秒 select floor(sysdate - to_date('20020405','yyyymmdd')) from dual; /设置两个日期之间的天数;/ select count(*)from ( select rownum-1 rnum from all_objects where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002-02-01','yyyy-mm-dd')+1 ) where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' ) not in ( '1', '7' ) select TO_CHAR(SYSDATE,'DDD'),sysdate from dual /显示今天是一年中的第几天;/ /计算时间差 注:oracle时间差是以天数为单位,所以换算成年月,日 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual // 时间差-年 select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual //时间差-月 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual //时 间差-天 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))24) as spanHours from dual // 时间差-时 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))2460) as spanMinutes from dual //时间差-分 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))246060) as spanSeconds from dual //时间差-秒/ /TO_DATE格式(以时间:2007-11-02 13:45:25为例) Year: yy two digits 两位年 显示值:07 yyy three digits 三位年 显示值:007 yyyy four digits 四位年 显示值:2007 Month: mm number 两位月 显示值:11 mon abbreviated 字符集表示 显示值:11月,若是英文版,显示nov month spelled out 字符集表示 显示值:11月,若是英文版,显示november Day: dd number 当月第几天 显示值:02 ddd number 当年第几天 显示值:02 dy abbreviated 当周第几天简写 显示值:星期五,若是英文版,显示fri day spelled out 当周第几天全写 显示值:星期五,若是英文版,显示friday ddspth spelled out, ordinal twelfth/ /日期的比较/ /在今天之前:/ select * from up_date where update < to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') select * from up_date where update <= to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') /在今天只后:/ select * from up_date where update > to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') select * from up_date where update >= to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') /精确时间:/ select * from up_date where update = to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') /在某段时间内:/ select * from up_date where update between to_date('2007-07-07 00:00:00','yyyy-mm-dd hh24:mi:ss') and to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') select * from up_date where update < to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') and update > to_date('2007-07-07 00:00:00','yyyy-mm-dd hh24:mi:ss') select * from up_date where update <= to_date('2007-09-07 00:00:00','yyyy-mm-dd hh24:mi:ss') and update >= to_date('2007-07-07 00:00:00','yyyy-mm-dd hh24:mi:ss') /日期时间间隔操作/   /*当前时间减去7分钟的时间 */  select sysdate,sysdate - interval '7' MINUTE from dual /*当前时间减去7小时的时间 */  select sysdate - interval '7' hour from dual /*当前时间减去7天的时间 */  select sysdate - interval '7' day from dual /当前时间减去7月的时间/ select sysdate,sysdate - interval '7' month from dual /当前时间减去7年的时间/ select sysdate,sysdate - interval '7' year from dual /时间间隔乘以一个数字/ select sysdate,sysdate - 8 *interval '2' hour from dual /返回当前时间 年月日小时分秒毫秒/   select to_char(current_timestamp(5),'DD-MON-YYYY HH24:MI:SSxFF') from dual; --返回当前 时间的秒毫秒,可以指定秒后面的精度(最大=9)   select to_char(current_timestamp(9),'MI:SSxFF') from dual; /Oracle SQL 语句对时间操作的总结/ /在SQL语句中,常常用会对时间(或日期)进行一些处理,下面是比较通用的一些语句: 延迟: sysdate+(5/24/60/60) 在系统时间基础上延迟5秒 sysdate+5/24/60 在系统时间基础上延迟5分钟 sysdate+5/24 在系统时间基础上延迟5小时 sysdate+5 在系统时间基础上延迟5天 add_months(sysdate,-5) 在系统时间基础上延迟5月 add_months(sysdate,-512) 在系统时间基础上延迟5年 */ /上月末的日期:/ select last_day(add_months(sysdate, -1)) from dual; /本月的最后一秒:/ select trunc(add_months(sysdate,1),'MM') - 1/24/60/60 from dual /本周星期一的日期:/ select trunc(sysdate,'day')+1 from dual /年初至今的天数:/ select ceil(sysdate - trunc(sysdate, 'year')) from dual; /今天是今年的第几周 :/ select to_char(sysdate,'fmww') from dual /今天是本月的第几周:/ SELECT TO_CHAR(SYSDATE,'WW') - TO_CHAR(TRUNC(SYSDATE,'MM'),'WW') + 1 AS "weekOfMon" FROM dual /本月的天数/ SELECT to_char(last_day(SYSDATE),'dd') days FROM dual /今年的天数/ select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual /下个星期一的日期/ SELECT Next_day(trunc(SYSDATE),'monday') FROM dual ================================ /计算工作日方法/ create table t(s date,e date); alter session set nls_date_format = 'yyyy-mm-dd'; insert into t values('2003-03-01','2003-03-03'); insert into t values('2003-03-02','2003-03-03'); insert into t values('2003-03-07','2003-03-08'); insert into t values('2003-03-07','2003-03-09'); insert into t values('2003-03-05','2003-03-07'); insert into t values('2003-02-01','2003-03-31'); -- 这里假定日期都是不带时间的,否则在所有日期前加trunc即可。 select s,e,e-s+1 total_days, trunc((e-s+1)/7)*5 + length(replace(substr('01111100111110',to_char(s,'d'),mod(e-s+1,7)),'0','')) work_days from t; -- drop table t; ======================================================== /判断当前时间是上午下午还是晚上/ SELECT CASE WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 6 AND 11 THEN '上午' WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 11 AND 17 THEN '下午' WHEN to_number(to_char(SYSDATE,'hh24')) BETWEEN 17 AND 21 THEN '晚上' END FROM dual; ========================================================== /Oracle 中的一些处理日期/ /将数字转换为任意时间格式.如秒:需要转换为天/小时/ SELECT to_char(floor(TRUNC(936000/(6060))/24))||'天'||to_char(mod(TRUNC(936000/(6060)),24))||'小时' FROM DUAL TO_DATE格式 /*Day: dd number 12 dy abbreviated fri day spelled out friday ddspth spelled out, ordinal twelfth Month: mm number 03 mon abbreviated mar month spelled out march Year: yy two digits 98 yyyy four digits 1998 24小时格式下时间范围为: 0:00:00 - 23:59:59.... 12小时格式下时间范围为: 1:00:00 - 12:59:59 .... 日期和字符转换函数 用法(to_date,to_char) */ 2. select to_char( to_date(222,'J'),'Jsp') from dual /*显示Two Hundred Twenty-Two */ /*3. 求某天是星期几 */ select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual; select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual; /设置日期语言/ ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN'; /*也可以这样 */ TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American') /*4. 两个日期间的天数 */ select floor(sysdate - to_date('20020405','yyyymmdd')) from dual; /*5. 时间为null的用法 */ select id, active_date from table1 UNION select 1, TO_DATE(null) from dual; /注意要用TO_DATE(null)/ /*6. a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd') 那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。 所以,当时间需要精确的时候,觉得to_char还是必要的 日期格式冲突问题 输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01' */ alter system set NLS_DATE_LANGUAGE = American alter session set NLS_DATE_LANGUAGE = American /*或者在to_date中写 */ select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual; /注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多, 可查看/ select * from nls_session_parameters select * from V$NLS_PARAMETERS 8. select count(*) from ( select rownum-1 rnum from all_objects where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002- 02-01','yyyy-mm-dd')+1 ) where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' ) not in ( '1', '7' ) /*查找2002-02-28至2002-02-01间除星期一和七的天数 在前后分别调用DBMS_UTILITY.GET_TIME, 然后将结果相减(得到的是1/100秒, 而不是毫秒). */ 9. select months_between(to_date('01-31-1999','MM-DD-YYYY'), to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL; 1 select months_between(to_date('02-01-1999','MM-DD-YYYY'), to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL; 1.03225806451613 /*10. Next_day的用法 Next_day(date, day) */ /*Monday-Sunday, for format code DAY Mon-Sun, for format code DY 1-7, for format code D */ 11 select to_char(sysdate,'hh:mi:ss') TIME from all_objects /*注意:第一条记录的TIME 与最后一行是一样的 可以建立一个函数来处理这个问题 */ create or replace function sys_date return date is begin return sysdate; end; select to_char(sys_date,'hh:mi:ss') from all_objects; /*12. 获得小时数 */ SQL> select sysdate ,to_char(sysdate,'hh') from dual; SYSDATE TO_CHAR(SYSDATE,'HH') 2003-10-13 19:35:21 07 SQL> select sysdate ,to_char(sysdate,'hh24') from dual; SYSDATE TO_CHAR(SYSDATE,'HH24') 2003-10-13 19:35:21 19 /*获取年月日与此类似 */ /*13. 年月日的处理 / select older_date, newer_date, years, months, abs( trunc( newer_date- add_months( older_date,years12+months ) ) ) days from ( select trunc(months_between( newer_date, older_date )/12) YEARS, mod(trunc(months_between( newer_date, older_date )), 12 ) MONTHS, newer_date, older_date from ( select hiredate older_date, add_months(hiredate,rownum)+rownum newer_date from emp ) ) /*14. 处理月份天数不定的办法 */ select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual /*16. 找出今年的天数 */ select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual /*闰年的处理方法 */ to_char( last_day( to_date('02' | | :year,'mmyyyy') ), 'dd' ) /*如果是28就不是闰年 */ /*17. yyyy与rrrr的区别 / /'YYYY99 TO_C yyyy 99 0099 rrrr 99 1999 yyyy 01 0001 rrrr 01 2001 18.不同时区的处理 */ select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate from dual; /*19. 5秒钟一个间隔 */ Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS') from dual TO_DATE(FL TO_CH 2007-01-01 60368 /*SSSSS表示5位秒数 */ /*20. 一年的第几天 */ select TO_CHAR(SYSDATE,'DDD'),sysdate from dual TO_ SYSDATE 017 2007-01-17 /21.计算小时,分,秒,毫秒 / select Days, A, TRUNC(A24) Hours, TRUNC(A2460 - 60TRUNC(A24)) Minutes, TRUNC(A246060 - 60TRUNC(A2460)) Seconds, TRUNC(A246060100 - 100TRUNC(A2460*60)) mSeconds from ( select trunc(sysdate) Days, sysdate - trunc(sysdate) A from dual ) select * from tabname order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss'); /*// floor((date2-date1) /365) 作为年 floor((date2-date1, 365) /30) 作为月 mod(mod(date2-date1, 365), 30) 作为日. */ /*22.next_day函数 */ /*next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。 1 2 3 4 5 6 7 日 一 二 三 四 五 六 */ select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))2460*60 from dual /*日期 返回的是天 然后 转换为ss */ select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))2460 from dual ; select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24 from dual ; select (sysdate-to_date('2012-07-23 12:55:45','yyyy-mm-dd hh24:mi:ss'))*24 from dual ; select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))2460*60 from dual ; Oracle中TO_DATE格式 TO_DATE格式(以时间:2007-11-02 13:45:25为例) Year: yy two digits 两位年 显示值:07 yyy three digits 三位年 显示值:007 yyyy four digits 四位年 显示值:2007 Month: mm number 两位月 显示值:11 mon abbreviated 字符集表示 显示值:11月,若是英文版,显示nov month spelled out 字符集表示 显示值:11月,若是英文版,显示november Day: dd number 当月第几天 显示值:02 ddd number 当年第几天 显示值:02 dy abbreviated 当周第几天简写 显示值:星期五,若是英文版,显示fri day spelled out 当周第几天全写 显示值:星期五,若是英文版,显示friday ddspth spelled out, ordinal twelfth Hour: hh two digits 12小时进制 显示值:01 hh24 two digits 24小时进制 显示值:13 Minute: mi two digits 60进制 显示值:45 Second: ss two digits 60进制 显示值:25 其它 Q digit 季度 显示值:4 WW digit 当年第几周 显示值:44 W digit 当月第几周 显示值:1 24小时格式下时间范围为: 0:00:00 - 23:59:59.... 12小时格式下时间范围为: 1:00:00 - 12:59:59 .... 日期和字符转换函数用法(to_date,to_char) select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') as nowTime from dual; //日期转化为字符串 select to_char(sysdate,'yyyy') as nowYear from dual; //获取时间的年 select to_char(sysdate,'mm') as nowMonth from dual; //获取时间的月 select to_char(sysdate,'dd') as nowDay from dual; //获取时间的日 select to_char(sysdate,'hh24') as nowHour from dual; //获取时间的时 select to_char(sysdate,'mi') as nowMinute from dual; //获取时间的分 select to_char(sysdate,'ss') as nowSecond from dual; //获取时间的秒 select to_date('2004-05-07 13:23:44','yyyy-mm-dd hh24:mi:ss') from dual// select to_char( to_date(222,'J'),'Jsp') from dual 显示Two Hundred Twenty-Two 3.求某天是星期几 select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day') from dual; 星期一 select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual; monday 设置日期语言 ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN'; 也可以这样 TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American') 两个日期间的天数 select floor(sysdate - to_date('20020405','yyyymmdd')) from dual; 时间为null的用法 select id, active_date from table1 UNION select 1, TO_DATE(null) from dual; 注意要用TO_DATE(null) 6.月份差 a_date between to_date('20011201','yyyymmdd') and to_date('20011231','yyyymmdd') 那么12月31号中午12点之后和12月1号的12点之前是不包含在这个范围之内的。 所以,当时间需要精确的时候,觉得to_char还是必要的 日期格式冲突问题 输入的格式要看你安装的ORACLE字符集的类型, 比如: US7ASCII, date格式的类型就是: '01-Jan-01' alter system set NLS_DATE_LANGUAGE = American alter session set NLS_DATE_LANGUAGE = American 或者在to_date中写 select to_char(to_date('2002-08-26','yyyy-mm-dd'),'day','NLS_DATE_LANGUAGE = American') from dual; 注意我这只是举了NLS_DATE_LANGUAGE,当然还有很多, 可查看 select * from nls_session_parameters select * from V$NLS_PARAMETERS select count(*) from ( select rownum-1 rnum from all_objects where rownum <= to_date('2002-02-28','yyyy-mm-dd') - to_date('2002- 02-01','yyyy-mm-dd')+1 ) where to_char( to_date('2002-02-01','yyyy-mm-dd')+rnum-1, 'D' ) not in ( '1', '7' ) 查找2002-02-28至2002-02-01间除星期一和七的天数 在前后分别调用DBMS_UTILITY.GET_TIME, 让后将结果相减(得到的是1/100秒, 而不是毫秒). 查找月份 select months_between(to_date('01-31-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL; 1 select months_between(to_date('02-01-1999','MM-DD-YYYY'),to_date('12-31-1998','MM-DD-YYYY')) "MONTHS" FROM DUAL; 1.03225806451613 Next_day的用法 Next_day(date, day) Monday-Sunday, for format code DAY Mon-Sun, for format code DY 1-7, for format code D 11 select to_char(sysdate,'hh:mi:ss') TIME from all_objects 注意:第一条记录的TIME 与最后一行是一样的 可以建立一个函数来处理这个问题 create or replace function sys_date return date is begin return sysdate; end; select to_char(sys_date,'hh:mi:ss') from all_objects; 12.获得小时数 extract()找出日期或间隔值的字段值 SELECT EXTRACT(HOUR FROM TIMESTAMP '2001-02-16 2:38:40') from offer SQL> select sysdate ,to_char(sysdate,'hh') from dual; SYSDATE TO_CHAR(SYSDATE,'HH') -------------------- --------------------- 2003-10-13 19:35:21 07 SQL> select sysdate ,to_char(sysdate,'hh24') from dual; SYSDATE TO_CHAR(SYSDATE,'HH24') -------------------- ----------------------- 2003-10-13 19:35:21 19 13.年月日的处理 select older_date, newer_date, years, months, abs( trunc( newer_date- add_months( older_date,years*12+months ) ) ) days from ( select trunc(months_between( newer_date, older_date )/12) YEARS, mod(trunc(months_between( newer_date, older_date )),12 ) MONTHS, newer_date, older_date from ( select hiredate older_date, add_months(hiredate,rownum)+rownum newer_date from emp ) ) 14.处理月份天数不定的办法 select to_char(add_months(last_day(sysdate) +1, -2), 'yyyymmdd'),last_day(sysdate) from dual 16.找出今年的天数 select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual 闰年的处理方法 to_char( last_day( to_date('02' | | :year,'mmyyyy') ), 'dd' ) 如果是28就不是闰年 17.yyyy与rrrr的区别 'YYYY99 TO_C yyyy 99 0099 rrrr 99 1999 yyyy 01 0001 rrrr 01 2001 18.不同时区的处理 select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdate from dual; 19.5秒钟一个间隔 Select TO_DATE(FLOOR(TO_CHAR(sysdate,'SSSSS')/300) * 300,'SSSSS') ,TO_CHAR(sysdate,'SSSSS') from dual 2002-11-1 9:55:00 35786 SSSSS表示5位秒数 20.一年的第几天 select TO_CHAR(SYSDATE,'DDD'),sysdate from dual 310 2002-11-6 10:03:51 21.计算小时,分,秒,毫秒 select Days, A, TRUNC(A24) Hours, TRUNC(A2460 - 60TRUNC(A24)) Minutes, TRUNC(A246060 - 60TRUNC(A2460)) Seconds, TRUNC(A246060100 - 100TRUNC(A2460*60)) mSeconds from ( select trunc(sysdate) Days, sysdate - trunc(sysdate) A from dual ) select * from tabname order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss'); // floor((date2-date1) /365) 作为年 floor((date2-date1, 365) /30) 作为月 d(mod(date2-date1, 365), 30)作为日. 23.next_day函数 返回下个星期的日期,day为1-7或星期日-星期六,1表示星期日 next_day(sysdate,6)是从当前开始下一个星期五。后面的数字是从星期日开始算起。 1 2 3 4 5 6 7 日 一 二 三 四 五 六 select (sysdate-to_date('2003-12-03 12:55:45','yyyy-mm-dd hh24:mi:ss'))2460*60 from ddual 日期 返回的是天 然后 转换为ss 24,round舍入到最接近的日期 select sysdate S1, round(sysdate) S2 , round(sysdate,'year') YEAR, round(sysdate,'month') MONTH , round(sysdate,'day') DAY from dual 25,trunc[截断到最接近的日期,单位为天] ,返回的是日期类型 select sysdate S1, trunc(sysdate) S2, //返回当前日期,无时分秒 trunc(sysdate,'year') YEAR, //返回当前年的1月1日,无时分秒 trunc(sysdate,'month') MONTH , //返回当前月的1日,无时分秒 trunc(sysdate,'day') DAY //返回当前星期的星期天,无时分秒 from dual 26,返回日期列表中最晚日期 select greatest('01-1月-04','04-1月-04','10-2月-04') from dual 27.计算时间差 注:oracle时间差是以天数为单位,所以换算成年月,日 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual //时间差-年 select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual //时间差-月 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual //时间差-天 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24) as spanHours from dual //时间差-时 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60) as spanMinutes from dual //时间差-分 select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60*60) as spanSeconds from dual //时间差-秒 28.更新时间 注:oracle时间加减是以天数为单位,设改变量为n,所以换算成年月,日 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n*365,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-年 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),add_months(sysdate,n) as newTime from dual //改变时间-月 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-日 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-时 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-分 select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-秒 29.查找月的第一天,最后一天 SELECT Trunc(Trunc(SYSDATE, 'MONTH') - 1, 'MONTH') First_Day_Last_Month, Trunc(SYSDATE, 'MONTH') - 1 / 86400 Last_Day_Last_Month, Trunc(SYSDATE, 'MONTH') First_Day_Cur_Month, LAST_DAY(Trunc(SYSDATE, 'MONTH')) + 1 - 1 / 86400 Last_Day_Cur_Month FROM dual;

保持可爱mmm 2020-04-15 23:33:10 0 浏览量 回答数 0
阿里云大学 云服务器ECS com域名 网站域名whois查询 开发者平台 小程序定制 小程序开发 国内短信套餐包 开发者技术与产品 云数据库 图像识别 开发者问答 阿里云建站 阿里云备案 云市场 万网 阿里云帮助文档 免费套餐 开发者工具 SQL审核 小程序开发制作 视频内容分析 企业网站制作 视频集锦 代理记账服务 2020阿里巴巴研发效能峰会 企业建站模板 云效成长地图 高端建站 人工智能 阿里云云栖号 云栖号案例 云栖号直播