Oracle 快速选择原因的方法

Oracle 快速选择原因的方法,oracle,Oracle,我有大约1000万条记录,它们的表结构是这样的 ------------------------------------------- BARCODE | PRICE | BRAND ------------------------------------------- 1001001000111 | 1 USD | A 1001001000112 | 1 USD | B 1001001000113 | 1 USD | A 1001001000114 | 1 USD | B 100

我有大约1000万条记录,它们的表结构是这样的

-------------------------------------------
 BARCODE      | PRICE | BRAND 
-------------------------------------------
1001001000111 | 1 USD | A
1001001000112 | 1 USD | B
1001001000113 | 1 USD | A
1001001000114 | 1 USD | B
1001001000115 | 1 USD | C
 . . .
我想得到条码值,其中brand等于B;这是我的问题

SELECT BARCODE 
FROM myTable 
WHERE BRAND='B';
我花了很多时间等待结果,所以我尝试将
Where
条件从
Where BRAND='B'
更改为
BRAND NOT IN('a','B','C',…)
。它似乎比('A'、'B'、'C'、…)中元素量
的第一次查询要快。
很小,但只要('A'、'B'、'C'、'D'、…)中元素量
越来越大,查询就会越来越慢

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


请帮我解决这个问题。

有多个问题需要解决

我有一张大桌子,大约有1000万张唱片

只要
1000万行
就可以让你说这个表是巨大的?大小是多少?列数据类型是什么?我有一个包含
50亿行的表
,我可以在几秒钟内选择所需的行。如何通过行数测量大小?当您谈论数据库中的大量数据时,请确保您提到的是数据的大小,而不是行数。1000万行可以是
500KB
1GB

回到要求上来,

我想得到条码值,其中brand等于B

Oracle optimizer足够聪明,可以决定是进行全表扫描还是使用索引。话虽如此,您必须收集最新的统计数据。此外,如果您计算出基数估计值,那么您实际上可以决定创建一个索引

基于有限的信息,我的建议是在
品牌
列上创建一个索引

CREATE INDEX barcd_indx ON mytable(BRAND);
其中BRAND=B

为什么不在字符串文本周围使用单引号?应将字符串值括在单引号内:

WHERE BRAND='B';

有许多问题需要解决

我有一张大桌子,大约有1000万张唱片

只要
1000万行
就可以让你说这个表是巨大的?大小是多少?列数据类型是什么?我有一个包含
50亿行的表
,我可以在几秒钟内选择所需的行。如何通过行数测量大小?当您谈论数据库中的大量数据时,请确保您提到的是数据的大小,而不是行数。1000万行可以是
500KB
1GB

回到要求上来,

我想得到条码值,其中brand等于B

Oracle optimizer足够聪明,可以决定是进行全表扫描还是使用索引。话虽如此,您必须收集最新的统计数据。此外,如果您计算出基数估计值,那么您实际上可以决定创建一个索引

基于有限的信息,我的建议是在
品牌
列上创建一个索引

CREATE INDEX barcd_indx ON mytable(BRAND);
其中BRAND=B

为什么不在字符串文本周围使用单引号?应将字符串值括在单引号内:

WHERE BRAND='B';

若并没有品牌索引,那个么你们最终会做一个完整的表格扫描

如果有一个关于品牌的索引,但是表的很大一部分是针对品牌B的,那么查询优化器可能会认为完整的表扫描仍然是最好的方法


如果brand上有一个索引,B是相当有选择性的,表示表中相对较小的部分,但优化器仍然选择进行完整表扫描,然后,您的统计数据可能会过时,您应该尝试在表上收集新的统计数据。

如果没有品牌索引,那么您将最终执行完整的表扫描

如果有一个关于品牌的索引,但是表的很大一部分是针对品牌B的,那么查询优化器可能会认为完整的表扫描仍然是最好的方法


如果brand上有一个索引,并且B是相当有选择性的,表示表中相对较小的部分,但优化器仍然选择进行完整表扫描,那么您的统计数据可能已过时,您应该尝试在表中收集新的统计数据。

首先检查硬件设置。这里我有一张和你的相似的桌子

 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秒在我的桌面上,在生产数据库上,预期会有更好的结果

首先检查硬件设置。这里我有一张和你的相似的桌子

 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秒在我的桌面上,在生产数据库上,预期会有更好的结果

选项1

根据品牌列对表进行分区。 如果品牌A、C的记录较少,则可以在一个分区中保存这些记录。 如果品牌B有更多记录,您可以为品牌B设置一个分区