快速选择原因的方法

时间:2015-07-22 14:22:08

标签: oracle

我有大约1000万条记录,其表格结构如下

-------------------------------------------
 BARCODE      | PRICE | BRAND 
-------------------------------------------
1001001000111 | 1 USD | A
1001001000112 | 1 USD | B
1001001000113 | 1 USD | A
1001001000114 | 1 USD | B
1001001000115 | 1 USD | C
 . . .

我想获得品牌等于B的条形码值;这是我的疑问。

SELECT BARCODE 
FROM myTable 
WHERE BRAND='B';

我花了很多时间等待结果,所以我尝试将Where条件从Where BRAND='B'更改为BRAND NOT IN ('A','B','C',..)。它似乎比第一个查询更快,元素in ('A','B','C',..)的数量很小,但只要元素in ('A','B','C','D',...)的数量变得越来越大,查询就越来越慢。

获取数据的最快方法是什么?

请帮我解决这个问题。

4 个答案:

答案 0 :(得分:0)

有许多问题需要解决。

  

我有大约1000万条记录的巨大表格

只有10 million行会让您说该表格巨大?什么是尺寸?列数据类型是什么?我有一个5 billion rows的表,我可以在几秒钟内选择我想要的行。如何根据行数测量大小?当您谈论数据库中的大量数据时,请确保提及数据的大小而不是行数。 1000万行可以是500KB1GB

回到要求,

  

我想获得品牌等于B的条形码值

Oracle优化器非常聪明,可以决定是进行全表扫描还是使用 INDEX 。话虽如此,您必须收集最新的统计信息。另外,如果您算出基数估算值,那么您实际上可以决定创建索引。

根据有限的信息,我的建议是在BRAND列上创建一个索引。

CREATE INDEX barcd_indx ON mytable(BRAND);
  

BRAND = B;

为什么不会在字符串文字周围使用 单引号?您应该将字符串值括在单引号中:

WHERE BRAND='B';

答案 1 :(得分:0)

如果Brand上没有索引,那么您将最终进行全表扫描。

如果Brand上有索引,但该表的很大一部分是针对品牌B的,则查询优化器可能会认为全表扫描仍然是最好的方法。

如果品牌上有索引,并且B相当有选择性地代表表格的一小部分,但优化程序仍然选择进行全表扫描,那么您的统计数据可能是陈旧的,您应该尝试收集新的桌上的统计数据。

答案 2 :(得分:0)

首先检查您的硬件设置。在这里,我有一张与你相似的表

 SQL> select count(*), count(distinct brand) from my10m;

  COUNT(*) COUNT(DISTINCTBRAND)
 ---------- --------------------
   10000000                   19

  SQL> select round(BYTES/(1024*1024)) MB from dba_segments where segment_name = 'MY10M';

          MB
  ----------
         296

启动SQL * Plus并检查扫描表所需的时间

  SQL> set timi on;
  SQL> set autotrace traceonly
  SQL> set array 5000
  SQL> select * from  my10m;

  10000000 rows selected.

  Elapsed: 00:00:10.10

  Execution Plan
  ----------------------------------------------------------
  Plan hash value: 2382977685

  ---------------------------------------------------------------------------
  | Id  | Operation         | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
  ---------------------------------------------------------------------------
  |   0 | SELECT STATEMENT  |       |    10M|   316M| 10314   (1)| 00:02:04 |
  |   1 |  TABLE ACCESS FULL| MY10M |    10M|   316M| 10314   (1)| 00:02:04 |
  --------------------------------------------------------------------------- 

所以,在我的情况下,完全扫描表需要10秒钟。这是一个简单的基准,所以
具有过滤条件的查询不应该比这更糟糕。 运行此基准测试并将经过的时间与您的查询进行比较。

另请注意,我将ARRAYSIZE设置为5000,这可以减少网络往返次数,并可以加快查询速度。你不会说你如何访问 日期,但很可能你也可能增加获取大小。

注意 - 10秒在我的桌面上,在生产数据库上预期会有更好的结果。

答案 3 :(得分:0)

选项1

根据品牌栏对表格进行分区。 如果说品牌A,C的记录较少,您可以将它们放在一个分区中。 如果品牌B有更多记录,您可以为该特定品牌设置一个分区。

选项2

您还可以考虑在列品牌上创建位图索引。