2010-08-19 64 views
3
SELECT count(*) c FROM full_view WHERE verified > (DATE (NOW()) - INTERVAL 30 DAY) 

如果我运行该查询,它需要一秒钟的时间,但如果我切换比较运算符,它需要使用eons。现在第一种方式计数= 0和第二种方式计数= 120000,但如果我只计算整个表,也需要几微秒。MySQL - 为什么COUNT的“大于”快,但“小于”需要永久?

但是有一些事情正在进行,因为如果查询完成,它会在此后超快运行。 MySQL正在缓存查询或正确的东西?那么,我不想依靠缓存来确保网站不会挂起。

这似乎是无意义的:如果它能够快速计算大于特定日期的所有事物,为什么它需要更长的时间来计算相反的结果呢?无论哪种方式,它必须查看整个表的权利?所有它需要返回的是一个数字,所以带宽不应该成为问题。

解释上查询:

1, 'SIMPLE', 'b', 'range', 'updated,verified_index', 'updated', '3', '', 28, 'Using where'`  
1, 'SIMPLE', 'l', 'eq_ref', 'PRIMARY', 'PRIMARY', '4', 'xyz_main.b.loc_id', 1, 'Using index' 
1, 'SIMPLE', 'f', 'ALL', '', '', '', '', 2214, '' 

编辑:

这可能是一些利益,我发现这个信息,当我运行查询:

Handler_read_rnd_next:

  • 254436689(whe Ñ做小于)
  • 2(用于大于)

Key_read_requests: 314393 VS 33(33是当使用对所有的统计信息的最大数目大于)

Handler_read_key: 104303与1

绕过视图并直接在主表上运行查询消除了缓慢。那么我需要做些什么来加速它?该观点基本上是这样的:

SELECT x, y, z, verified FROM table1 LEFT JOIN table2 on tab2_ID = table2.ID LEFT JOIN table3 on tab3_ID = table3.ID 

解决: 弗兰基导致我在正确的方向。第二张加入的表格(公司表格)通过公司的全文名称加入。我最近才决定为该表添加一个整数键。名字专栏应该被索引,但我可能已经弄糟了。无论如何,我重新组织了一切。我将主表中的外键转换为与公司表的整数ID相匹配,而不是完整的公司名称。我重新索引了每个表中的这些列,然后我更新了视图以反映新的连接点。现在它在两个方向上立即运行。 :)所以我猜整数键是关键。问题不复存在,但我仍然觉得我的原始问题并没有真正解决。

感谢您的帮助球员。

+0

我假设'full_view'是一个视图,那是什么定义? – 2010-08-19 23:23:23

+1

'解释计划'告诉你什么? – 2010-08-19 23:23:35

+0

full_view包含与其他两个表格左侧连接的主表(带有已验证的列)。主表是人员,另外两个表则加入地点和公司信息。这非常简单。 – Moss 2010-08-20 00:05:42

回答

3

请运行以下查询并发布结果。

EXPLAIN SELECT count(*) c 
FROM full_view 
WHERE verified > (DATE (NOW()) - INTERVAL 30 DAY) 

长期遗忘的EXPLAIN几乎总是带来的东西了! ;


编辑1:
这可能是进攻线:

1, 'SIMPLE', 'f', 'ALL', '', '', '', '', 2214, '' 

ALL有指出,有一个全表扫描。

您可以进一步挖掘到Explain syntax on this diagram

会尽力看看那里的差异去...


编辑2:
This doc will sure make things much clearer on the Explain output. Please check it out.


编辑3:
步骤一步analys的解释命令。

1, 'SIMPLE', 'b', 'range', 'updated,verified_index', 'updated', '3', '', 28, 'Using where'`  
1 - id 
SIMPLE - simple select, not using sub-queries 
b - table name 
range - only rows that are in a given range are retrieved, using an index 
updated,verified_index - are both possible keys 
updated - was the key eventually used 
3 - key lenght 
'' - this is the ref column and would show which columns or constants are compared to the index name in the key column to select rows from the table. 
28 - number of rows mysql believes it must examine to execute the query 
Using where - self explanatory 
2

我的猜测是Date(Now())的减法是需要很长时间才能处理的。对于已经小于Date(Now())verified的值,评估可以被短路,因为在那时它必须是假的(当比较“大于”时)。

在比较“小于”的情况下,必须在每种情况下减去日期时间,无论当前值如何,因为无法在表达式之前将表达式逻辑地结论为真或假评估日期时间扣除

但这只是一个猜测 - 把它与一粒盐。

+0

使用明确的日期也需要永久。 – Moss 2010-08-20 00:06:16

+0

@Moss有趣的,也许我的想法是离基地然后。如何扭转比较的顺序?而不是'A < B', do 'B > A',看看是否需要这么长时间 - 它应该执行完全一样的(我猜想) – 2010-08-20 01:36:07

+0

有趣的想法,但为时已晚,现在就尝试。我用更好的键/索引解决了这个问题。 – Moss 2010-08-20 01:40:50

0

如果您在表中有verified的索引,那么限制性更强的COUNT(>>)会更快。 COUNT(*)没有WHERE子句可以快速返回,因为可以从表/索引统计中收集计数。

+0

将比较放在count中是更好的语法,但它不会加快速度。我确实有一个关于'verified'的索引。 – Moss 2010-08-20 00:12:10

+0

实际上,这种方法使得它在两个方向上都很慢。 – Moss 2010-08-20 00:23:29

1

可能有这样的情况,即有统计数据告诉数据库引擎在30天前没有验证记录。在这种情况下,它甚至不必读取表格,而是从统计直方图中获取信息。

相关问题