2016-04-25 101 views
1

我一直在玩弄MySQL和sqlalchemy来收集和存储数据。在周末,我收集了大约2万条推文/小时的推文,并将它们放置在由他们的推特ID索引的表格raw_tweets中。我期待〜1,000,000行,但是当我运行时MySQL查询挂在`SELECT COUNT(*)`

SELECT COUNT(*) from raw_tweets; 

查询只是挂起。我等了几分钟,什么都没有。我对sql的知识相当有限。桌子上有锁吗?这会导致它挂起而不会导致错误?我该如何去诊断/解决这个问题?

P.S.它看起来像我在桌子上的所有查询都挂了。

+4

显然桌子上有一个锁。 – HLGEM

+1

你可以规范化你的查询,比如,从raw_tweets中选择COUNT(id); –

+1

我们假设,你的'id'字段是一个主键。所以作为@SagarR悲伤,使用'SELECT COUNT(id)FROM raw_teweets'应该更快。 – vaso123

回答

2

最有可能它不挂,但需要非常多的时间来执行。

如果表引擎是InnoDB,SELECT COUNT(*)必须从表中读取所有行(以便对它们进行计数),并且如果数据库处于大量使用状态,则操作需要很长时间。

这是记录在Limits on InnoDB Tables页:

InnoDB的不守行的内部计数的表,因为并发事务可能会“看到”的行不同数量在同一时间。要处理SELECT COUNT(*) FROM t语句,InnoDB会扫描表的索引,如果索引不完全位于缓冲池中,则需要一些时间。为了快速计数,您必须使用自己创建的计数器表,并让应用程序根据插入操作对其进行更新并将其删除。如果大致的行数足够,可以使用SHOW TABLE STATUS

如上所述,如果一个近似的行数是足够让你再运行:

SHOW TABLE STATUS WHERE NAME = 'raw_tweets' 

,并期待到结果的Rows列。

请注意:

  • 通过SHOW TABLE STATUS返回的行数是近似的;它可以脱离实际值几个百分点(当桌子很小时,差距会更大);
  • SHOW TABLE STATUS在每次后续运行中返回的值都会发生变化,即使表中没有写入活动也是如此。
+0

这正是我所需要的。由于我只是在验证数据是否被收集,所以近似数字已经足够好了。我不知道InnoDB的限制。 – Shatnerz

+0

如果你的表正在使用旧的'MyISAM'引擎,那么'SELECT COUNT(*)'会立即完成,因为引擎保持该值并更新它。现在转换它可能已经太晚了。 – axiac

1

你可以运行在另一个数据库连接下面的(如果你有足够的权限来这样做):

SHOW FULL PROCESSLIST; 

这可能会显示所有查询/当前数据库上运行的进程。在该列表中,你可能会看到,如果有一些锁在桌子上

mysql> show full processlist; 
+---------+------------+-----------------+------------+---------+------+-------+-----------------------+ 
| Id  | User  | Host   | db   | Command | Time | State | Info     | 
+---------+------------+-----------------+------------+---------+------+-------+-----------------------+ 
| 121904 | user01  | localhost  | user_db | Locked | 0 |  | SELECT * FROM usr_tbl | 
| 1186598 | root  | localhost  | NULL  | Query | 0 | NULL | show full processlist | 

你应该在CommandInfo列细看设置。

0
SELECT row_count = SUM(row_count) 
    FROM sys.dm_db_partition_stats 
    WHERE [object_id] = OBJECT_ID('raw_tweets') 
    AND index_id IN (0,1); 

试试这个

+0

这确实是一个很好的回应,但你能解释为什么它更快?谢谢 –

+0

@AxelGuilmin:谢谢你的赞赏,首先你写道你已经在使用索引表,所以我的解决方案部分适合你的问题,因为我们正在处理index_id,所以它的速度相当快,另一件事你只需要行数并且您的ID具有主键,因此最好使用Count(PRIMARYKEY FIELD)而不是Count(*)。 –