1. 理解函数的三态1

    VOLATILE:

     volatile函数没有限制,可以修改数据(如执行delete,insert,update), 使用同样的参数调用可能返回不同的值.

    STABLE:

     不允许修改数据, PG8.0以及以上版本不允许在volatile函数中使用非SELECT|PERFORM语句.
    使用同样的参数调用返回同样的结果,在事务中有这个特性的也归属stable.

    IMMUTABLE:

      不允许修改数据, 使用同样的参数调用返回同样的结果.

    备注:Pg 8.0以及以上版本不允许在stable或immutable函数中执行非select|perform语句.

    示例:

     test=# create table tbl(id int primary key, info text, crt_time timestamp);
    CREATE TABLE
    test=# create or replace function f_tbl(i_id int) returns void as $$
    test$# declare
    test$# begin
    test$# update tbl set crt_time=now() where id=i_id;
    test$# end;
    test$# $$ language plpgsql stable;
    CREATE FUNCTION
    test=# \set VERBOSITY verbose
    test=# select f_tbl(1);
    ERROR: 0A000: UPDATE is not allowed in a non-volatile function
    背景: SQL statement "update tbl set crt_time=now() where id=i_id"
    PL/pgSQL function f_tbl(integer) line 4 at SQL statement
    位置: _SPI_execute_plan_internal, spi.c:2951

    漏洞:在stable或immutable函数中调用volatile函数是可以的.

    示例:

     test=# alter function f_tbl(int) volatile;
    ALTER FUNCTION
    test=# create or replace function f_tbl1(i_id int) returns void as $$
    test$# declare
    test$# begin
    test$# perform f_tbl(i_id); -- 在stable或immutable函数中调用volatile函数是可以的.
    test$# end;
    test$# $$ language plpgsql stable;
    CREATE FUNCTION
    test=#
    test=# insert into tbl values(1,'test',now());
    INSERT 0 1
    test=# select * from tbl;
    id | info | crt_time
    ----+------+----------------------------
    1 | test | 2022-11-10 11:46:05.854350
    (1 行记录) test=# select f_tbl1(1);
    f_tbl1
    -------- (1 行记录) test=# select * from tbl;
    id | info | crt_time
    ----+------+----------------------------
    1 | test | 2022-11-10 11:46:33.153699
    (1 行记录)

    同样的参数多次调用.

    volatile 函数相同的参数,多次调用返回结果可能不一样.

     kbstattuple扩展插件可以参考KingbaseES在线手册
    https://help.kingbase.com.cn/v8/development/sql-plsql/ref-extended-plug-in/kbstattuple.html?highlight=kbstattuple test=# create extension kbstattuple ;
    CREATE EXTENSION
    test=# \dx+ kbstattuple ;
    对象用于扩展 "kbstattuple"
    对象描述
    ---------------------------------------
    function pg_relpages(regclass)
    function pg_relpages(text)
    function pgstatginindex(regclass)
    function pgstathashindex(regclass)
    function pgstatindex(regclass)
    function pgstatindex(text)
    function pgstattuple_approx(regclass)
    function pgstattuple(regclass)
    function pgstattuple(text)
    (9 行记录) test=# create table t2(id int);
    CREATE TABLE
    test=# select pg_relpages('t2');
    pg_relpages
    -------------
    0
    (1 行记录) test=# insert into t2 values (1);
    INSERT 0 1
    test=# select pg_relpages('t2'); -- 返回值变化
    pg_relpages
    -------------
    1
    (1 行记录) test=# select proname,provolatile from pg_proc where proname='pg_relpages';
    proname | provolatile
    -------------+-------------
    pg_relpages | v
    pg_relpages | v
    (2 行记录)

    stable, immutable函数同样的参数多次调用返回结果不变.

    在事务中多次调用返回结果一致的也可归属于stable.

     test=# select now();
    now
    -------------------------------
    2022-11-10 13:42:35.689740+08
    (1 行记录) test=# select now();
    now
    -------------------------------
    2022-11-10 13:42:36.756038+08
    (1 行记录) test=# begin;
    BEGIN
    test=# select now();
    now
    -------------------------------
    2022-11-10 13:42:39.037893+08
    (1 行记录) test=# select now();
    now
    -------------------------------
    2022-11-10 13:42:39.037893+08
    (1 行记录) test=# select provolatile,proname,proargtypes from pg_proc where proname='now';
    provolatile | proname | proargtypes
    -------------+---------+-------------
    s | now |
    (1 行记录) test=# select now();
    now
    -------------------------------
    2022-11-10 13:42:39.037893+08
    (1 行记录) test=# end;
    COMMIT
    test=# select now();
    now
    -------------------------------
    2022-11-10 13:43:31.772061+08
    (1 行记录)

    immutable函数同stable, 同样的参数多次调用结果一致.

     test=# select proname,provolatile from pg_proc where proname='abs';
    proname | provolatile
    ---------+-------------
    abs | i
    abs | i
    abs | i
    abs | i
    abs | i
    abs | i
    abs | i
    (7 行记录) test=# select abs(-10);
    abs
    -----
    10
    (1 行记录) test=# select abs(-10);
    abs
    -----
    10
    (1 行记录) test=# begin;
    BEGIN
    test=# select abs(-10);
    abs
    -----
    10
    (1 行记录) test=# select abs(-10);
    abs
    -----
    10
    (1 行记录) test=# end;
    COMMIT
    test=# select abs(-10);
    abs
    -----
    10
    (1 行记录)
  2. VOLATILE/STABLE/IMMUTABLE区别:

VOLATILE

	volatile函数不能被优化器作为优化条件.
1)例如单SQL处理多行时不能减少volatile函数的调用次数,
2)不能使用volatile函数创建函数索引,
3)在过滤条件中使用volatile函数时, 不能走索引扫描.
在同一个查询中, 同样参数的情况下可能被多次执行(QUERY有多行返回/扫描的情况下).

STABLE

	1)优化器可根据实际场景优化stable函数的调用次数, 同样的参数多次调用可能减少成单次调用.
2)stable函数可以用于优化器选择合适的索引扫描, 因为索引扫描仅评估被比较的值一次, 后多次比较.
3)stable和volatile函数都不能用于创建函数索引, 只有immutable函数可以用于创建函数索引.

IMMUTABLE

	优化器在处理immutable函数时, 先评估函数结果, 将结果替换为常量.
  1. 理解函数的三态2

     test=# create table t3(id int);
    CREATE TABLE
    test=# insert into t3 values(1),(1),(1),(2),(2),(2);
    INSERT 0 6
    test=#
    test=# create or replace function f_t3(id int) returns int as $$
    test$# declare
    test$# begin
    test$# raise notice 'Called.';
    test$# return id;
    test$# end;
    test$# $$ language plpgsql stable; -- stable 状态
    CREATE FUNCTION
    test=# select * from t3 where f_t3(id) =1;
    -- f_t3(id) --这里id是变量,不能被优化器优化,因此函数调用了6次.
    test=# select * from t3 where f_t3(id) =1;
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    id
    ----
    1
    1
    1
    (3 行记录) select * from t3 where f_t3(1) =1;
    -- 这里使用常量调用f_t3()所以可以被优化器优化.
    test=# select * from t3 where f_t3(1) =1;
    NOTICE: 00000: Called. -- 函数只被调用一次
    位置: exec_stmt_raise, pl_exec.c:3908
    id
    ----
    1
    1
    1
    2
    2
    2
    (6 行记录) 把函数改成volatile后, 函数不能被优化. test=# alter function f_t3(int) volatile;
    ALTER FUNCTION
    test=# select proname,provolatile from pg_proc where proname='f_t3';
    proname | provolatile
    ---------+-------------
    f_t3 | v
    (1 行记录) test=# select * from t3 where f_t3(1) =1;
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    NOTICE: 00000: Called.
    位置: exec_stmt_raise, pl_exec.c:3908
    id
    ----
    1
    1
    1
    2
    2
    2
    (6 行记录)

根据函数的实际情况设置稳定态, 可以达到优化效果.

例如f_t3函数调用一次耗时1秒, 并且是stable的状态,以上例子可以减少5秒的查询时间.使用volatile态则需要6秒.

优化器在处理immutable函数时,先评估函数结果,将结果替换为常量.

	test=# explain select * from t2 where id>abs(-1);
QUERY PLAN
-----------------------------------------------------
Seq Scan on t2 (cost=0.00..41.75 rows=847 width=4)
Filter: (id > 1)
(2 行记录) 因为abs(int)是immutable函数,这里abs(-1)替换成常量1. 如果把函数改成stable, 那么将不会替换成常量. test=# alter function abs(int) stable;
ALTER FUNCTION
test=# select proname,provolatile from pg_proc where proname='abs';
proname | provolatile
---------+-------------
abs | i
abs | i
abs | i
abs | i
abs | i
abs | s
abs | i
(7 行记录) test=# explain select * from t2 where id>abs(-1);
QUERY PLAN
-----------------------------------------------------
Seq Scan on t2 (cost=0.00..48.10 rows=847 width=4)
Filter: (id > abs('-1'::integer))
(2 行记录) 由于abs(int)被改成stable了, 将不会替换成常量

在prepared statement中使用需要注意区别. 后面会有例子.

只有immutable函数可以创建函数索引.

	test=# create table t4(id int,info timestamp(0));
CREATE TABLE
test=# \set VERBOSITY verbose
test=# create index idx_t4_1 on t4(to_char(info,'yyyymmdd'));
ERROR: 42P17: functions in index expression must be marked IMMUTABLE
位置: ComputeIndexAttrs, indexcmds.c:1940 test=# create table t5(id int primary key, info text);
CREATE TABLE
test=# insert into t5 select generate_series(1,100000),md5(random()::text);
INSERT 0 100000 test=# alter function abs(int) volatile;
ALTER FUNCTION
test=# test=# \d+ t4
数据表 "public.t4"
栏位 | 类型 | 校对规则 | 可空的 | 预设 | 存储 | 统计目标 | 描述
------+--------------------------------+----------+--------+------+-------+----------+------
id | integer | | | | plain | |
info | timestamp(0) without time zone | | | | plain | |
访问方法 heap test=# \d+ t5
数据表 "public.t5"
栏位 | 类型 | 校对规则 | 可空的 | 预设 | 存储 | 统计目标 | 描述
------+---------+----------+----------+------+----------+----------+------
id | integer | | not null | | plain | |
info | text | | | | extended | |
索引:
"t5_pkey" PRIMARY KEY, btree (id)
访问方法 heap

索引扫描时, 用于过滤条件的表达式只被评估一次后, 再与索引值进行比较判断是否满足条件.

	test=# explain select * from t5 where id<abs(10);
QUERY PLAN
----------------------------------------------------------
Seq Scan on t5 (cost=0.00..2341.00 rows=33333 width=37)
Filter: (id < abs(10))
(2 行记录)

只有stable函数和immutable函数符合索引扫描的刚性需求.

	test=# alter function abs(int) stable;
ALTER FUNCTION
test=# explain select * from t5 where id<abs(-100);
QUERY PLAN
--------------------------------------------------------------------
Index Scan using t5_pkey on t5 (cost=0.29..9.99 rows=97 width=37)
Index Cond: (id < abs('-100'::integer))
(2 行记录) test=# alter function abs(int) immutable;
ALTER FUNCTION
test=# explain select * from t5 where id<abs(-100);
QUERY PLAN
--------------------------------------------------------------------
Index Scan using t5_pkey on t5 (cost=0.29..9.99 rows=97 width=37)
Index Cond: (id < 100)
(2 行记录) volatile函数同样的输入参数可能返回不同值,在一个查询中将被多次调用,不符合索引扫描规则.
stable和immutable同样的参数返回值不变,因此可以作为索引扫描的比较值,优化器允许走索引扫描.
  1. 理解函数的三态3

    函数内的每条查询语句的数据可见性:

    VOLATILE

     snapshot为函数内的每个query开始时的snapshot. 因此对外部已提交的数据时可见的.

    STABLE

     snapshot为外部调用函数的QUERY的snapshot, 函数内部始终保持这个snapshot.

    IMMUTABLE

     同stable

测试:

	test=# create or replace function f_t6() returns void as $$
test$# declare
test$# r record;
test$# begin
test$# for i in 1..10 loop
test$# for r in select * from t6 loop
test$# raise notice 'loop:%,t6:%.',i,r;
test$# end loop;
test$# perform pg_sleep(5);
test$# end loop;
test$# end;
test$# $$ language plpgsql volatile;
CREATE FUNCTION test=# create table t6(id int,info text);
CREATE TABLE --执行过程中,新建连接往t6表插入新数据,volatile函数察觉新增行
test=# select f_t6();
NOTICE: loop:2,t6:(1,test).
NOTICE: loop:3,t6:(1,test).
NOTICE: loop:4,t6:(1,test).
NOTICE: loop:5,t6:(1,test).
NOTICE: loop:5,t6:(1,test1).
NOTICE: loop:6,t6:(1,test).
NOTICE: loop:6,t6:(1,test1).
NOTICE: loop:6,t6:(1,test3).
NOTICE: loop:7,t6:(1,test).
NOTICE: loop:7,t6:(1,test1).
NOTICE: loop:7,t6:(1,test3).
NOTICE: loop:7,t6:(1,test5).
NOTICE: loop:8,t6:(1,test).
NOTICE: loop:8,t6:(1,test1).
NOTICE: loop:8,t6:(1,test3).
NOTICE: loop:8,t6:(1,test5).
NOTICE: loop:9,t6:(1,test).
NOTICE: loop:9,t6:(1,test1).
NOTICE: loop:9,t6:(1,test3).
NOTICE: loop:9,t6:(1,test5).
NOTICE: loop:10,t6:(1,test).
NOTICE: loop:10,t6:(1,test1).
NOTICE: loop:10,t6:(1,test3).
NOTICE: loop:10,t6:(1,test5).
NOTICE: loop:10,t6:(1,hello).
f_t6
------ (1 行记录) test=# insert into t6 values(1,'test');
INSERT 0 1
test=# insert into t6 values(1,'test1');
INSERT 0 1
test=# insert into t6 values(1,'test3');
INSERT 0 1
test=# insert into t6 values(1,'test5');
INSERT 0 1
test=# insert into t6 values(1,'hello');
INSERT 0 1
test=# --更改稳定态为 stable immutable
test=# alter function f_t6() stable;
ALTER FUNCTION
test=# truncate table t6;
TRUNCATE TABLE
test=# select f_t6();
f_t6
------ (1 行记录) --f_t6()执行过程中对t6变更, 函数不感知.
test=# insert into t6 values(1,'hello');
INSERT 0 1
test=# insert into t6 values(1,'test5');
INSERT 0 1
test=# insert into t6 values(1,'test3');
INSERT 0 1
test=# insert into t6 values(1,'test3');
INSERT 0 1
test=#
  1. 理解函数的三态4

    STABLE和IMMUTABLE的区别:

     在SELECT子句中,优化器对stable和immutable区别对待.

    测试:

     test=# create table t7(id int);
    CREATE TABLE
    test=# insert into t7 values (1),(2),(3);
    INSERT 0 3
    test=# create or replace function f_t7(i int) returns int as $$
    test$# declare
    test$# begin
    test$# raise notice 'called';
    test$# return i;
    test$# end;
    test$# $$ language plpgsql stable;
    CREATE FUNCTION -- SELECT子句中, stable函数不被优化器优化
    test=# select f_t7(1),* from t7;
    NOTICE: called --多次调用
    NOTICE: called
    NOTICE: called
    f_t7 | id
    ------+----
    1 | 1
    1 | 2
    1 | 3
    (3 行记录) test=# alter function f_t7(int) immutable;
    ALTER FUNCTION -- immutable函数被替换成常量, 只执行一次.
    test=# select f_t7(1),* from t7;
    NOTICE: called --一次调用
    f_t7 | id
    ------+----
    1 | 1
    1 | 2
    1 | 3
    (3 行记录) --当函数为stable时, 优化器没有处理这种过滤条件, 理论上是可以优化为一次调用f_t7(1)的. 目前仅仅immutable被优化.
    test=# alter function f_t7(int) stable;
    ALTER FUNCTION 当使用索引扫描时, stable在这里只会执行一次. test=# select * from t7 where id=f_t7(1);
    NOTICE: called --有一次为explain的评估输出.
    NOTICE: called
    NOTICE: called
    NOTICE: called
    id
    ----
    1
    (1 行记录) -- 将id=f_t7(1)替换成f_t7(1)=1
    test=# select * from t7 where f_t7(1)=1;
    NOTICE: called
    id
    ----
    1
    2
    3
    (3 行记录) test=# explain select * from t7 where f_t7(1)=1;
    QUERY PLAN
    ------------------------------------------------------------
    Result (cost=0.25..35.65 rows=2540 width=4)
    One-Time Filter: (f_t7(1) = 1)
    -> Seq Scan on t7 (cost=0.25..35.65 rows=2540 width=4)
    (3 行记录) test=# alter function f_t7(int) immutable;
    ALTER FUNCTION
    test=# explain select * from t7 where f_t7(1)=1;
    NOTICE: called
    QUERY PLAN
    ------------------------------------------------------
    Seq Scan on t7 (cost=0.00..35.40 rows=2540 width=4)
    (1 行记录)
  2. 理解函数的三态

    VOLATILE

     1)volatile函数没有限制, 可以修改数据(如执行delete, insert , update).
    2)使用同样的参数调用可能返回不同的值.
    3)volatile函数不能被优化器选择作为优化条件.(例如减少调用, 函数索引, 索引扫描不允许使用volatile函数)
    4)在同一个查询中, 同样参数的情况下可能被多次执行(QUERY有多行返回/扫描的情况下).
    5)snapshot为函数内的每个query开始时的snapshot. 因此对在函数执行过程中, 外部已提交的数据可见.(仅限于调用函数的事务隔离级别为read committed)

STABLE

	1)stable和immutable函数, 函数内不允许修改数据.(如PGver>=8.0 函数内不可执行非SELECT|PERFORM语句.)
2)使用同样的参数调用返回同样的结果, 在事务中有这个特性的也归属stable.
3)优化器可根据实际场景优化stable函数的调用次数, 同样的参数多次调用可减少成单次调用.
4)stable和immutable函数可用于优化器选择合适的索引扫描, 因为索引扫描仅评估被比较的表达式一次, 后多次与索引值进行比较.
5)stable和volatile函数都不能用于创建函数索引, 只有immutable函数可以用于创建函数索引.
6)stable和immutable函数, snapshot为外部调用函数的QUERY的snapshot, 函数内部始终保持这个snapshot, 外部会话带来的的数据变更不被反映到函数执行过程中.

IMMUTABLE

	1)不允许修改数据, 使用同样的参数调用返回同样的结果.
2)优化器在处理immutable函数时, 先评估函数结果, 将结果替换为常量.
3)因此使用约束优化查询的场景中也只识别immutable函数.

STABLE和IMMUTABLE的区别

	1)STABLE函数在SELECT和WHERE子句中不被优化, 仅仅当使用索引扫描时WHERE子句对应的STABLE函数才会被优化为1次调用.
2)在PREPARED STATEMENT中的使用区别:
3)IMMUTABLE函数在PLAN时以常量替代,STABLE函数在EXECUTE阶段被执行.
4)因此IMMUTABLE函数参数为常量时,在PREPARED STATEMENT场景只执行一次,而STABLE函数被多次执行.

函数稳定性通过查看PG_PROC/SYS_PROC.PROVOLATILE得到

	PROVOLATILE 说明函数是仅仅只依赖 于它的输入参数 ,还是会被外部 因素影响。
值 I 表示“不变的”函数,它对于相同的输入总是输出相同的结果。
值 S 表示“稳定的”函数,它的结果(对于固定输入在一次扫描内不会变化。
值 V 表示“不稳定的”函数,它的结果在任何时候都可能变化。
使用V页表示函数具有副作用,所以对它们的调用无法得到优化。

KingbaseES函数三态的更多相关文章

  1. KingbaseES 函数稳定性与SQL性能

    背景:客户现场的一次艰苦的调优过程(https://www.cnblogs.com/kingbase/p/16015834.html),让我觉得非常有必要让数据库用户了解函数的不同稳定性属性,及其对于 ...

  2. KingbaseES函数如何返回结果集

    函数返回值一般是某一类型值,如int,varchar,date等,返回结果集时就需要用到setof语法. 创建数据 create table class(id number primary key, ...

  3. KingbaseES 与Oracle 函数稳定性对于性能影响差异比较

    一.函数的属性 KingbaseES 函数在定义时有三种稳定性级别:volatile.stable 和 immutable.默认情况下,创建函数的稳定性为volatile.以下是这三种函数的区别: V ...

  4. KingbaseES时间函数的比较

    KingbaseES提供了多种的时间函数,这些函数在使用过程中存在哪些不同? **同一事务** test=# begin test-# for i in 1.. 10 loop test-# rais ...

  5. KingbaseES 格式化函数

    KingbaseES格式化函数提供一套有效的工具用于把各种数据类型(日期/时间.integer.floating point和numeric)转换成格式化的字符串以及反过来从格式化的字符串转换成指定的 ...

  6. KingbaseES 实现MYSQL hex/unhex 函数

    MySQL 的hex 和 unhex 函数类似于KingbaseES 的encode 和 decoding,实现字符与16进制之间的转换. 一.先看MySQL例子 mysql> select h ...

  7. KingbaseES 行列转换函数

    关键字:    行专列,列转行, pivot, unpivot 行列转换是在数据分析中经常用到的一项功能,KingbaseES从V8R6C3B0071版本开始通过扩展插件(kdb_utils_func ...

  8. KingbaseES sys_blocking_pids 函数

    会话出现了锁等待,想要快速查询到堵塞的会话,可以使用 sys_blocking_pids 函数来实现这一目的. sys_blocking_pids:获取哪些会话阻塞了某个会话(输入参数). sys_b ...

  9. KingbaseES DENSE_RANK 函数用法

    DENSE_RANK()函数用于为结果集分区内的每一行分配一个排名,排名值之间没有差距,函数为结果集的每个分区中的每一行分配一个等级. 与 RANK() 函数不同的是,DENSE_RANK() 函数总 ...

  10. KingbaseES 中可以通过构造一个聚集函数来实现mysql的any_value功能。

    示例 创建函数 create function coalesce_("anyelement","anyelement") returns "anyel ...

随机推荐

  1. 【Azure API 管理】Azure APIM服务集成在内部虚拟网络后,在内部环境中打开APIM门户使用APIs中的TEST功能失败

    问题描述 使用微软API管理服务(Azure API Management),简称APIM. 因为公司策略要求只能内部网络访问,所以启用了VNET集成.集成方式见: (在内部模式下使用 Azure A ...

  2. pagehelper使用有误导致sql多了一个limit

    接口测试报告中发现时不时有一个接口报错,但再跑一次又没有这个报错了.报错信息是sql异常,sql中有两个limit.查看后台代码和XXmapper.xml,发现确实只有一个limit.一开始开发以为是 ...

  3. Window10开机键盘映射

    一.映射工具 1.github地址 https://github.com/susam/uncap 2.映射方式 (1)CapsLock映射成ESC键 uncap 0x1b:0x14 (2)CapsLo ...

  4. 基于python的数学建模---logicstic回归

    樱花数据集的Logistic回归 绘制散点图 import matplotlib.pyplot as plt import numpy as np from sklearn.datasets impo ...

  5. HDC.Cloud Day | 全国首场上海站告捷,聚开发者力量造梦、探梦、筑梦

    摘要:11月20日,首个华为云开发者日HDC.Cloud Day在上海成功举行. 本文分享自华为云社区<HDC.Cloud Day | 全国首场上海站告捷,聚开发者力量造梦.探梦.筑梦>, ...

  6. <二>自己实现简单的string

    我们结合运算符重载知识实现string 类 在自己实现的String类中可以参考C++中string的方法 例如构造,加法,大小比较,长度,[] 等操作. 当前的MyString 类中,暂时不加入迭代 ...

  7. ubuntu 22.04安装多个gcc

    sudo apt install gcc-9 g++-9 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 90 - ...

  8. Pycharm2022.1.3安装教程(包含基础使用配置)

    pycharm的下载安装及使用 以我的Pycharm2022.1.3为例 首先去官网下载professtional(专业版)版本 2022.1.3版本Pycharm软件 https://www.jet ...

  9. 2022csp普及组真题:乘方(pow)

    2022csp普及组真题:乘方(pow) 题目 [题目描述] 小文同学刚刚接触了信息学竞赛,有一天她遇到了这样一个题:给定正整数 a 和 b ,求 a^b 的值是多少. a^b 即 b 个 a 相乘的 ...

  10. 研究光度立体法阶段性小结和优化(可20ms获取4个2500*2000灰度图的Normal Map)。

    这个东西是我接触的第一个非2D方面的算法,到目前为止其实也没有完全搞定,不过可能短时间内也无法突破.先把能搞定的搞定吧. 这个东西也有一大堆参考资料,不过呢,搜来搜去其实也就那些同样的东西,个人觉得就 ...