oracle - 我应该如何在 Oracle 中使用 varchar2 列对索引进行范围分区?这是一个坏主意吗?

标签 oracle oracle10g partitioning

我使用的是 Oracle 10g 企业版。

我们的 Oracle 数据库中的表存储另一个文本列的 soundex 值表示。我们正在使用一种自定义 soundex 实现,其中 soundex 值比传统 soundex 算法(例如 Oracle 使用的算法)生成的值更长。这确实不是重点。

基本上,我有一个 varchar2 列,其中的值包含单个字符,后跟动态数量的数值(例如“A12345”、“S382771”等)。该表由另一列分区,但我想向 soundex 列添加分区索引,因为它经常被搜索。当尝试使用 soundex 列的第一个字符添加范围分区索引时,效果很好:

create index IDX_NAMES_SOUNDEX on NAMES_SOUNDEX (soundex)
global partition by range (soundex) (
    partition IDX_NAMES_SOUNDEX_PART_A values less than ('B'),  -- 'A%'
    partition IDX_NAMES_SOUNDEX_PART_B values less than ('C'),  -- 'B%'
    ...
);

但是,为了更均匀地分配分区的大小,我想通过前两个字符定义一些分区,如下所示:

create index IDX_NAMES_SOUNDEX on NAMES_SOUNDEX (soundex)
global partition by range (soundex) (
    partition IDX_NAMES_SOUNDEX_PART_A5 values less than ('A5'), -- 'A0% - A4%'
    partition IDX_NAMES_SOUNDEX_PART_A values less than ('B'),   -- 'A4% - A9%'
    partition IDX_NAMES_SOUNDEX_PART_B values less than ('C'),   -- 'B%'
    ...
);

我不确定如何使用 varchar2 列正确划分分区范围。我确信这是一个不太理想的选择,所以也许有人可以推荐更好的解决方案。这是我的表中 soundex 数据的分布:

-----------------------------------
|  SUBSTR(SOUNDEX,1,1)  |  COUNT  |
-----------------------------------
|                    A  | 6476349 |
|                    B  |  854880 |
|                    D  |  520676 |
|                    F  | 1200045 |
|                    G  |  280647 |
|                    H  | 3048637 |
|                    J  |  711031 |
|                    K  | 1336522 |
|                    L  |  348743 |
|                    M  | 3259464 |
|                    N  | 1510070 |
|                    Q  |  276769 |
|                    R  | 1263008 |
|                    S  | 3396223 |
|                    V  |  533844 |
|                    W  |  555007 |
|                    Y  |  348504 |
|                    Z  | 1079179 |
-----------------------------------

正如您所看到的,分布并不均匀,这就是为什么我想使用前两个字符而不是仅第一个字符来定义范围分区。

建议?

谢谢!

最佳答案

你的问题到底是什么?

您不知道如何将表格分成 n 个相等的部分以避免倾斜吗?

您可以使用分析函数percentile_disc() 来做到这一点。

这是一个 n=100 的 SQL PLUS 示例,我承认它不是很复杂,但它可以完成这项工作。

set pages 0
set lines 200

drop table random_strings;

create table random_strings 
as 
select upper(dbms_random.string('A', 12)) rndmstr
from dual 
connect by level < 1000;


spool parts

select 'select '||level||'/100,percentile_disc('||level||
       '/100) within group (order by RNDMSTR) from random_strings;' 
       sql_statement
from dual 
connect by level <= 100
/

spool off

这将在文件 parts.lst 中输出:

select 1/100,percentile_disc(1/100) within group (order by RNDMSTR) from random_strings;                                                                                                                
select 2/100,percentile_disc(2/100) within group (order by RNDMSTR) from random_strings;                                                                                                                
select 3/100,percentile_disc(3/100) within group (order by RNDMSTR) from random_strings;                                                 
...
select 100/100,percentile_disc(100/100) within group (order by RNDMSTR) from random_strings;                                                 

现在您可以运行脚本 parts.lst 来获取分区值。每个分区最初将包含 1% 的数据。

脚本 parts.lst 将输出:

   ,01 AJUDRRSPGMNP
   ,02 AOMJZQPZASQZ
   ,03 AWDQXVGLLUSJ
   ,04 BIEPUHAEMELR
   .... 
   ,99 ZTMHDWTXUJAR
   1   ZYVJLNATVLOY

关于oracle - 我应该如何在 Oracle 中使用 varchar2 列对索引进行范围分区?这是一个坏主意吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1283228/

相关文章:

sql - 当我有表名时如何获取模式名 - Oracle

php - 在 Codeigniter 的库中连接另一个数据库

oracle - 为什么会出现 "missing right parenthesis"错误?

c# - System.Data.OracleClient 不适用于 64 位 Oracle 客户端

sql - 与日期比较时忽略 WHERE 子句中的时间戳

java - 如何将子记录的插入限制为N条记录?

sql - 在 Oracle/SQL 中如何选择列值保持不变的行

c# - 是否有与 C# 分区程序等效的 Java

Mysql分区索引

performance - 为什么在主表上查询很慢?