찾다
데이터 베이스MySQL 튜토리얼关于动态抽样(DynamicSampling)

本文将回答:什么是动态抽样?动态抽样有啥作用?以及不同级别的动态抽样的意思? 1、什么是动态采样? 动态抽样从 oracle 9i第2版引入。它使得优化器(CBO)在硬解析期间有能力抽样一个未分析的表 (any table that has been created and loaded but not ye


本文将回答:什么是动态抽样?动态抽样有啥作用?以及不同级别的动态抽样的意思?


1、什么是动态采样?
动态抽样从 oracle 9i第2版引入。它使得优化器(CBO)在硬解析期间有能力抽样一个未分析的表
(any table that has been created and loaded but not yet analyzed)的统计(决定表默认统计),并且可以验证优化器的”猜想“。
因其只在查询硬解析期间为优化器动态生成更好的统计,得名动态采样。


动态采样提供11个设置级别。注意:9i中其默认值为1 到了10g默认值为2


2、动态采样如何工作?
有两种使用方式:
△ 设置OPTIMIZER_DYNAMIC_SAMPLING参数,可以再实例和会话级别设置动态采样。
△ 使用DYNAMIC_SAMPLING hint


来看一下不使用动态采样的日子怎么过的
create table t
as
select owner, object_type
from all_objects
/




select count(*) from t;


COUNT(*)
------------------------
68076

code1: 禁用动态采样观察默认基数


set autotrace traceonly explain
SQL> select /*+ dynamic_sampling(t 0) */ * from t;


Execution Plan
------------------------------
Plan hash value: 1601196873


--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 16010 | 437K| 55 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T | 16010 | 437K| 55 (0)| 00:00:01 |
--------------------------------------------------------------------------



--注意0级别即为禁用动态采样,环境默认是开启动态采样的


执行计划显示基数:16010远低于上面查询的68076,明显不靠谱。


code2: 更加接近显示的基数
select * from t;


Execution Plan
------------------------------
Plan hash value: 1601196873


--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 77871 | 2129K| 56 (2)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T | 77871 | 2129K| 56 (2)| 00:00:01 |
--------------------------------------------------------------------------


Note
------------------------------------------
- dynamic sampling used for this statement




code3: 被高估的基数
SQL> delete from t;
68076 rows deleted.


SQL> commit;
Commit complete.


SQL> set autotrace traceonly explain
SQL> select /*+ dynamic_sampling(t 0) */ * from t;


Execution Plan
------------------------------
Plan hash value: 1601196873


--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 16010 | 437K| 55 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T | 16010 | 437K| 55 (0)| 00:00:01 |
--------------------------------------------------------------------------


SQL> select * from t;


Execution Plan
-----------------------------
Plan hash value: 1601196873


------------------------------------------------------------------------【本文来自鸿网互联 (http://www.68idc.cn)】--
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 28 | 55 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| T | 1 | 28 | 5 (0)| 00:00:01 |
--------------------------------------------------------------------------


Note
---------------------------------------
- dynamic sampling used for this statement



3、动态采样何时帮助优化器验证其猜测?
我们知道当使用DBMS_STATS收集了表信息后,优化器会得到以下统计:
1)表,行数,平均行宽等;
2)单独列,高低值,唯一值数量,直方图(可能)等;
3)单独索引,聚集因素,叶子块数量,索引高度等。


但注意这里面缺少了某些关键统计信息,例如表中不同列数据之间的关联!
假设你你有一个全球人口普查表!
一个属性是:出生月份MONTH_BORN_IN,另一个属性是:所属星座ZODIAC_SIGN。收集信息后,你问优化器出生在11月份的人数?
假设12个月人数正常分布,那么优化器很快给出答案是全量数据的1/12!再问一个:星座是双鱼座的人数呢?答案也是1/12!
迄今为止优化器对答如流!!!nice work!
但是第3个问题来了:出生在11月份并且星座是双鱼座的人数是多少呢?
明眼人转下脑子就知道答案是0(双鱼座2月19日-3月20日)!但是我们看优化器的答案:1/12/12!!! 多么异想天开的答案,思维定式!这样就会诞生差的执行计划,
也正是在此时我们的动态采样开始干预:


code4: 创建模拟数据
SQL > create table t
as select decode( mod(rownum,2), 0, 'N', 'Y' ) flag1,
decode( mod(rownum,2), 0, 'Y', 'N' ) flag2, a.*
from all_objects a
/
Table created.


SQL > create index t_idx on t(flag1,flag2);
Index created.


SQL > begin
dbms_stats.gather_table_stats
( user, 'T',
method_opt=>'for all indexed columns size 254' );
end;
/
PL/SQL procedure successfully completed.


SQL> select num_rows, num_rows/2,
num_rows/2/2 from user_tables
where table_name = 'T';


NUM_ROWS NUM_ROWS/2 NUM_ROWS/2/2
-------- ---------- ------------
68076 34038 17019


code5:验证一下上面的说法:
SQL> set autotrace traceonly explain
SQL> select * from t where flag1='N';


Execution Plan
------------------------------
Plan hash value: 1601196873


--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 33479 | 3432K| 292 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 33479 | 3432K| 292 (1)| 00:00:04 |
--------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("FLAG1"='N')


SQL> select * from t where flag2='N';


Execution Plan
----------------------------
Plan hash value: 1601196873


---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 34597 | 3547K| 292 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 34597 | 3547K| 292 (1)| 00:00:04 |
---------------------------------------------------------------------------


Predicate Information (identified by operation id):
---------------------------------------------------


1 - filter("FLAG2"='N')


--至此一切正常!so far, so good!


code5: here comes the problem
SQL> select * from t where flag1 = 'N' and flag2 = 'N';


Execution Plan
----------------------------
Plan hash value: 1601196873


--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 17014 | 1744K| 292 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 17014 | 1744K| 292 (1)| 00:00:04 |
--------------------------------------------------------------------------


Predicate Information (identified by operation id):
----------------------------------------------------


1 - filter("FLAG1" = 'N' AND "FLAG2" = 'N')


--验证了我们前面说的优化器此时异想天开了


code7: 动态采样听令,开始介入
SQL> select /*+ dynamic_sampling(t 3) */ * from t where flag1 = 'N' and flag2 = 'N';


Execution Plan
-----------------------------
Plan hash value: 470836197


------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 630 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 6 | 630 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | T_IDX | 6 | | 1 (0)| 00:00:01 |
------------------------------------------------------------------------------------


Predicate Information (identified by operation id):
----------------------------------------------------


2 - access("FLAG1"='N' AND "FLAG2"='N')


code8: 我们打开SQL_TRACE会看到以下语句:
SELECT /* OPT_DYN_SAMP */ /*+ ALL_ROWS IGNORE_WHERE_CLAUSE
NO_PARALLEL(SAMPLESUB) opt_param('parallel_execution_enabled', 'false')
NO_PARALLEL_INDEX(SAMPLESUB) NO_SQL_TUNE */ NVL(SUM(C1),:"SYS_B_00"),
NVL(SUM(C2),:"SYS_B_01"), NVL(SUM(C3),:"SYS_B_02")
FROM
(SELECT /*+ IGNORE_WHERE_CLAUSE NO_PARALLEL("T") FULL("T")
NO_PARALLEL_INDEX("T") */ :"SYS_B_03" AS C1, CASE WHEN "T"."FLAG1"=
:"SYS_B_04" AND "T"."FLAG2"=:"SYS_B_05" THEN :"SYS_B_06" ELSE :"SYS_B_07"
END AS C2, CASE WHEN "T"."FLAG2"=:"SYS_B_08" AND "T"."FLAG1"=:"SYS_B_09"
THEN :"SYS_B_10" ELSE :"SYS_B_11" END AS C3 FROM "T" SAMPLE BLOCK
(:"SYS_B_12" , :"SYS_B_13") SEED (:"SYS_B_14") "T") SAMPLESUB


可以看出来优化器在验证其猜想。。。


4、动态采样级别:
现在列出11个级别,详细请参考:http://docs.oracle.com/cd/B19306_01/server.102/b14211/stats.htm#i43032
1)Level 0: Do not use dynamic sampling.
0级:不使用动态采样。


2)Level 1: Sample all tables that have not been analyzed if the following criteria are met: (1) there is at least 1 unanalyzed table in the query; (2) this unanalyzed table is joined to another table or appears in a subquery or non-mergeable view; (3) this unanalyzed table has no indexes; (4) this unanalyzed table has more blocks than the number of blocks that would be used for dynamic sampling of this table. The number of blocks sampled is the default number of dynamic sampling blocks (32).
1级:满足以下条件则采样所有没被分析的表:
(1)查询中至少有一个未分析表;
(2)这个未分析表被关联另外一个表或者出现在子查询或非merge视图中;
(3)这个未分析表有索引;
(4)这个未分析表有多余动态采样默认的数据块数(默认是32块)。


3)Level 2: Apply dynamic sampling to all unanalyzed tables. The number of blocks sampled is two times the default number of dynamic sampling blocks.
2级:对所有未分析表进行动态采样。采样数据块数量是默认数量的2倍。


4)Level 3: Apply dynamic sampling to all tables that meet Level 2 criteria, plus all tables for which standard selectivity estimation used a guess for some predicate that is a potential dynamic sampling predicate. The number of blocks sampled is the default number of dynamic sampling blocks. For unanalyzed tables, the number of blocks sampled is two times the default number of dynamic sampling blocks.
3级:在2级基础上加上那些使用了猜想选择消除表,采样数据块数量等于默认数量。对于未分析表,采样数量2倍于默认数量。




5)Level 4: Apply dynamic sampling to all tables that meet Level 3 criteria, plus all tables that have single-table predicates that reference 2 or more columns. The number of blocks sampled is the default number of dynamic sampling blocks. For unanalyzed tables, the number of blocks sampled is two times the default number of dynamic sampling blocks.
4级:在3级基础上加上那些有单表谓词关联2个或多个列,采样数据块数量等于默认数量。对于未分析表,采样数量2倍于默认数量。




6)Levels 5, 6, 7, 8, and 9: Apply dynamic sampling to all tables that meet the previous level criteria using 2, 4, 8, 32, or 128 times the default number of dynamic sampling blocks respectively.
5,6,7,8,9级在4级基础上分别使用2,4,8,32,128倍于默认动态采样数据块数量。


7)Level 10: Apply dynamic sampling to all tables that meet the Level 9 criteria using all blocks in the table.
10级:在9级基础上对表中所有数据块进行采样。


5、什么时候适合采用动态采样?


这是一个狡猾的问题,没有一定使用经验,还真不好意思说。
通常:
1)我们使用3和4级进行动态采样。
2)如果我们SQL的解析时间很快但是执行时间巨慢,可以考虑使用动态采样。典型的就是数据仓库系统。
3)OLTP系统中都是一个SQL重复执行,解析和执行都在瞬息之间,所以不建议使用高级别的动态采样。这会给SQL带来硬解析消耗。
这个时候可以考虑SQL Profile,你可以理解为“静态采样”。

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
MySQL 문자열 유형 : 스토리지, 성능 및 모범 사례MySQL 문자열 유형 : 스토리지, 성능 및 모범 사례May 10, 2025 am 12:02 AM

mysqlStringTypESmpactStorageAndperformanceAsfollows : 1) charisfixed, adlaysamestoragespace.

MySQL 문자열 유형 이해 : Varchar, Text, Char 등MySQL 문자열 유형 이해 : Varchar, Text, Char 등May 10, 2025 am 12:02 AM

mysqlstringtypesincludevarchar, text, char, enum, and set.1) varcharisversatileforvariable-lengthstringsupciedlimit.2) textisidealforlargetextStorage whithoudfinedlength.3) charisfixed, witableforconsistentDatalikecodes.4)

MySQL의 문자열 데이터 유형은 무엇입니까?MySQL의 문자열 데이터 유형은 무엇입니까?May 10, 2025 am 12:01 AM

mysqloffersvariousstringdatatatypes : 1) charfixed-lengthstrings, 2) varcharforvariable-lengthtext, 3) binaryandvarbinaryforbinarydata, 4) blobandtextforlargedata 및 5) enumandsetforcontrolledInput.achtolledinput.CheachorciCificusessandperististicatististicatististics

새로운 MySQL 사용자에게 권한을 부여하는 방법새로운 MySQL 사용자에게 권한을 부여하는 방법May 09, 2025 am 12:16 AM

TograntpermissionSt

MySQL에서 사용자를 추가하는 방법 : 단계별 가이드MySQL에서 사용자를 추가하는 방법 : 단계별 가이드May 09, 2025 am 12:14 AM

ToadDuserSinMySqleFeffectially, 다음에 따르면, 다음 사항을 따르십시오

MySQL : 복잡한 권한이있는 새 사용자 추가MySQL : 복잡한 권한이있는 새 사용자 추가May 09, 2025 am 12:09 AM

toaddanewuser와 함께 complexpermissionsinmysql, followthesesteps : 1) createShereuser'NewUser '@'localhost'Identifiedby'pa ssword ';. 2) grantreadaccesstoalltablesin'mydatabase'withgrantselectonmydatabase.to'newuser'@'localhost';. 3) GrantWriteAccessto '

MySQL : 문자열 데이터 유형 및 콜라주MySQL : 문자열 데이터 유형 및 콜라주May 09, 2025 am 12:08 AM

MySQL의 문자열 데이터 유형에는 char, varchar, binary, varbinary, blob 및 텍스트가 포함됩니다. 콜라이트는 문자열의 비교와 분류를 결정합니다. 1. 차량은 고정 길이 스트링에 적합하고 Varchar는 가변 길이 스트링에 적합합니다. 2. 이진 및 바이너리는 이진 데이터에 사용되며 Blob 및 텍스트는 큰 객체 데이터에 사용됩니다. 3. UTF8MB4_UNICODE_CI와 같은 정렬 규칙은 상류 및 소문자를 무시하며 사용자 이름에 적합합니다. UTF8MB4_BIN은 사례에 민감하며 정확한 비교가 필요한 필드에 적합합니다.

MySQL : Varchars에는 몇 개의 길이를 사용해야합니까?MySQL : Varchars에는 몇 개의 길이를 사용해야합니까?May 09, 2025 am 12:06 AM

가장 좋은 mysqlvarchar 열 길이 선택은 데이터 분석을 기반으로하고, 향후 성장을 고려하고, 성능 영향을 평가하고, 문자 세트 요구 사항을 기반으로해야합니다. 1) 일반적인 길이를 결정하기 위해 데이터를 분석합니다. 2) 미래 확장 공간을 예약하십시오. 3) 성능에 대한 큰 길이의 영향에주의를 기울이십시오. 4) 문자 세트가 스토리지에 미치는 영향을 고려하십시오. 이러한 단계를 통해 데이터베이스의 효율성과 확장 성을 최적화 할 수 있습니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

PhpStorm 맥 버전

PhpStorm 맥 버전

최신(2018.2.1) 전문 PHP 통합 개발 도구

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기