2

我正在使用 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 |
-----------------------------------

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

建议?

谢谢!

4

3 回答 3

4

你的问题到底是什么?

您不知道如何将表格分成 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
于 2009-08-16T06:44:42.050 回答
1

除了 SOUNDEX 值之外,是否正在通过分区键搜索表?还是仅通过 SOUNDEX 列进行搜索?

如果您只是想在分区之间实现数据的均匀分布,您是否考虑过使用散列分区而不是范围分区?假设您为分区数量选择 2 的幂,这应该可以让您在分区之间实现相当均匀的数据分布。

于 2009-08-16T04:19:51.180 回答
0

跟我说话!你能告诉我你对这张表进行分区的原因是什么吗?听起来它是一个 OLTP 表,可能不需要分区。我们不想分区只是说我们是分区的。告诉我你想通过分区这个表来完成什么,我可以帮助你选择一个正确的分区方案。分区不等于更快的查询。在某些情况下,它实际上会导致您的查询变慢。

我在上面看到了您的一些其他想法,我认为您不需要对表进行分区。如果您的查询将在整个分区上进行聚合,那么您可能需要分区。如果您将拥有数亿行数据,您可能需要分区以帮助进行 DBA 维护。如果您只想让查询快速运行,那么主键索引就足够了。请告诉我

只需在所需列上创建一个全局索引。

于 2009-08-18T19:36:56.973 回答