即使使用 parallel(8) 提示,具有数百万条记录的表中的 Count(1) 也很慢

Posted

技术标签:

【中文标题】即使使用 parallel(8) 提示,具有数百万条记录的表中的 Count(1) 也很慢【英文标题】:Count(1) from a table having million records is slow even with parallel(8) hint 【发布时间】:2020-02-11 17:40:00 【问题描述】:

我正在尝试从具有 1.94 亿条记录的表中计算记录。使用了并行提示和索引快速扫描,但仍然很慢。请为附加的查询提出任何替代或改进想法。

SELECT
 /*+ parallel(cs_salestransaction 8)
 index_ffs(cs_salestransaction CS_SALESTRANSACTION_COMPDATE)
 index_ffs(cs_salestransaction CS_SALESTRANSACTION_AK1) */
 COUNT(1)
FROM cs_salestransaction
WHERE processingunitseq=38280596832649217
AND (compensationdate BETWEEN DATE '28-06-17' AND DATE '26-01-18'
OR eventtypeseq IN (16607023626823731, 16607023626823732, 16607023626823733, 16607023626823734));

这是执行计划:

[]

查询给出了结果,但计算了 1.94 亿需要 2 个小时。

编辑:


编辑代码以根据 Littlefoot 的建议添加 DATE。 使用实际列名编辑的代码。 我是堆栈溢出的新手,因此已将计划附加为图像。

【问题讨论】:

什么是es执行计划? @WernfriedDomscheit 已将其作为图像附加。我是堆栈溢出的新手。所以不知道如何以可读的格式复制粘贴它。 通常您会使用EXPLAIN PLAN FOR ... your statement;SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);SELECT DBMS_XPLAN.DISPLAY_PLAN from dual; 获得解释计划 "parallel(8) 提示":那么您的数据库服务器有多少 CPU?您执行此查询时还运行了什么? @APC 这是我查询缓慢的原因之一。许多会话在后台运行。谢谢 【参考方案1】:

另外,如果compensationdateDATE 数据类型,不要将其与字符串 进行比较(因为'28-JUL-17' 字符串)并强制Oracle 执行隐式转换和花时间在nothing上。切换到

compensationdate BETWEEN date '2017-07-28' and date '2018-01-26'

【讨论】:

谢谢。这加快了 SELECT * 查询并将时间减少到 1 秒(从 5 秒)。但是我的 SELECT COUNT(1) 仍然需要时间(仍在运行).. 是的,我昨天晚些时候想到了它。是的,对于 2 亿条记录来说,这很重要。【参考方案2】:

在 where 子句中包含 OR CONDITION 会忽略查询中索引的使用。你应该摆脱 OR 条件。可以有多种方法。其中一种方法是——

SELECT /*+ parallel(sales 8)
           index_ffs(sales ,sales_COMPDATE) 
           index_ffs(sales , sales_eventtypeseq )*/
       COUNT(1)
FROM sales 
WHERE processingunitseq=38
AND compensationdate BETWEEN TO_DATE('28-JUL-17') AND TO_DATE('26-JAN-18')
UNION ALL
SELECT /*+ parallel(sales 8)
           index_ffs(sales ,sales_COMPDATE) 
           index_ffs(sales , sales_eventtypeseq )*/
       COUNT(1)
FROM sales 
WHERE processingunitseq=38
AND compensationdate NOT BETWEEN TO_DATE('28-JUL-17') AND TO_DATE('26-JAN-18')  -- To avoid duplicates
AND eventtypeseq IN (1, 2, 3, 4);

其他建议,请贴出查询的执行计划。

【讨论】:

这将返回两行而不是一行,甚至可能读取整个表格两次。 这将读取表两次,但由于此查询将使用索引,因此执行速度会更快。具有 OR 条件根本不会使用 Index,并且性能会很差。 Oracle 可以使用带有OR 条件的索引。

以上是关于即使使用 parallel(8) 提示,具有数百万条记录的表中的 Count(1) 也很慢的主要内容,如果未能解决你的问题,请参考以下文章

highcharts工具提示格式数百万

对于具有数百万像素的 2D 未装箱像素阵列,建议使用哪种 Haskell 表示?

如何使用 pandas 或 python 将具有数百万行的表从 PostgreSQL 复制到 Amazon Redshift

在 Python 中合并具有数百万行的两个表

具有数百万行的 Django 表

如何在 SQL Server 中更新具有数百万行的大表?