简单计数查询的成本

Posted

技术标签:

【中文标题】简单计数查询的成本【英文标题】:Cost Of Simple count Query 【发布时间】:2015-09-18 06:38:19 【问题描述】:

我有一个关于表的简单计数的查询。根据下面的屏幕截图,除了单个索引在不同的列上之外,表上没有主键。

如何降低此查询的成本?

实际查询是:

即使我在 transactionno 列上创建了一个额外的索引,成本也没有差异。该表有 45 列。表的总大小为 520MB。

  CREATE TABLE TBL_COUNT 
   (    ROW_NUMBER NUMBER(22,0) NOT NULL ENABLE, 
    DATECREATED TIMESTAMP (6), 
    TRANSACTIONDATE VARCHAR2(64), 
    TRANSACTIONTIME VARCHAR2(64), 
    TRANSACTIONNO VARCHAR2(100), 
    FIRST_NAME VARCHAR2(100), 
    LAST_NAME VARCHAR2(100), 
    REG_NO VARCHAR2(30), 
    EMAIL VARCHAR2(100), 
    PURCHASE_TYPE VARCHAR2(50), 
    RA_STATUS VARCHAR2(50), 
    BSCS_CODE VARCHAR2(20), 
    ORACLE_ITEM_CODE VARCHAR2(100), 
    ORACLE_PACKAGE_CODE VARCHAR2(100), 
    SKU_CODE VARCHAR2(50), 
    ITEM_DESCRIPTIONS VARCHAR2(100), 
    MSISDN VARCHAR2(150), 
    QUANTITY NUMBER(22,0), 
    UNIT_PRICE NUMBER(22,2), 
    SERVICE_TAX NUMBER(22,2), 
    TOTAL_PRICE NUMBER(22,2), 
    PAYMENT_METHOD VARCHAR2(50), 
    PAYMENT_CHANNEL VARCHAR2(50), 
    PAYMENT_MERCHANT_ID VARCHAR2(50), 
    REGISTER_REGION VARCHAR2(30), 
    AR_INTERFACESTATUS VARCHAR2(30), 
    PAYMENT_STATUS VARCHAR2(30), 
    PAYMENT_DATE VARCHAR2(64), 
    PAYMENT_TIME VARCHAR2(64), 
    ISSUING_BANK VARCHAR2(50), 
    CREDIT_CARD_NO VARCHAR2(50), 
    CREDIT_CARD_REASON_CODE VARCHAR2(100), 
    BANK_APPROVAL_CODE VARCHAR2(30), 
    BANK_REGISTER_REGION VARCHAR2(30), 
    BANK_REF_NO VARCHAR2(30), 
    PRIMARY_CONTACT_NO VARCHAR2(30), 
    ALTERNATE_CONTACT_NO VARCHAR2(30), 
    REFERENCE_CONTACT_NO VARCHAR2(30), 
    PRODUCT_UID VARCHAR2(30), 
    BANK_BIN VARCHAR2(50), 
    SETTLEMENT_DATE TIMESTAMP (3), 
    SKU_TYPE VARCHAR2(50), 
    EXTERNAL_ORDER_NUMBER VARCHAR2(64), 
    GST_TAX_AMOUNT NUMBER(22,2), 
    GST_TAX_CODE VARCHAR2(255 )
   )   TABLESPACE TS ;

  CREATE INDEX USER.TBL_COUNT_INDEX ON USER.TBL_COUNT (DATECREATED) 
  TABLESPACE TS_IDX ;

【问题讨论】:

为什么你经常对大约 150 万行表执行 count(*) 足以关心查询的性能?除非您想定义主键(无论如何您都应该这样做),否则不可能有比执行表扫描更有效的方法。您可能会并行化查询,这会使其返回更快,但也会导致它在服务器上消耗更多资源。 更新了问题..请就此提出建议。 您的编辑未在transactionNo 上显示索引。你确定你创建了那个索引吗? 我已经在 transactionno 上创建了索引。但由于我没有发现成本有任何改善,所以我放弃了 您很可能需要索引,而您的问题可能归结为询问为什么查询不使用索引。发布您用于创建索引的 DDL。该指数的统计数据是否准确? transactionNo 的选择性如何?您是否绑定了正确的数据类型? transactionNo 似乎被定义为 varchar2,尽管名称暗示它是数字。 【参考方案1】:

任何索引都可以用于计数,只要它基于限制为 NOT NULL 的列,或者如果它保证为每一行保存一个值 - 例如位图索引,或 (my_column, 0) 上的索引。

或者,您可以使用 SAMPLE 子句获得估计的行数。

编辑:您说您在 transactionno 上创建了索引,并且正如 DDL 所示,它不受限制为 NOT NULL。要么在 ROW_NUMBER(唯一不为 NULL 的列)上创建索引,要么在 (transactionno, 0) 上创建基于函数的索引

【讨论】:

重点是当我正在为同一查询寻找其他表的解释计划时.. 它的成本较低,因为它使用主键。即使我在同一张表上创建了主键但没有改进,也会导致相同的成本。 请显示表和索引定义——按照您在问题中所说的方式,您创建的是索引,而不是主键。 我已经创建了主键,但是当我发现成本没有提高时,我放弃了。 请将它们添加到问题中 我在 transactionno 上创建了索引。但由于我没有发现成本有任何改善,所以我放弃了。

以上是关于简单计数查询的成本的主要内容,如果未能解决你的问题,请参考以下文章

简单计数查询超出 Impala 内存限制

以编程方式生成 MDX 行计数查询的最简单方法?

从 SQL 查询中捕获计数

计数器表的简单使用

Django 查询相关字段计数

WMI 性能计数器查询问题