and*_*bd1 13 mysql sql query-optimization
有没有办法进一步优化这个或者我是否应该满足于计算11M行需要9秒?
devuser@xcmst > mysql --user=user --password=pass -D marctoxctransformation -e "desc record_updates"
+--------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------+----------+------+-----+---------+-------+
| record_id | int(11) | YES | MUL | NULL | |
| date_updated | datetime | YES | MUL | NULL | |
+--------------+----------+------+-----+---------+-------+
devuser@xcmst > date; mysql --user=user --password=pass -D marctoxctransformation -e "select count(*) from record_updates where date_updated > '2009-10-11 15:33:22' "; date
Thu Dec 9 11:13:17 EST 2010
+----------+
| count(*) |
+----------+
| 11772117 |
+----------+
Thu Dec 9 11:13:26 EST 2010
devuser@xcmst > mysql --user=user --password=pass -D marctoxctransformation -e "explain select count(*) from record_updates where date_updated > '2009-10-11 15:33:22' "
+----+-------------+----------------+-------+--------------------------------------------------------+--------------------------------------------------------+---------+------+----------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------------+-------+--------------------------------------------------------+--------------------------------------------------------+---------+------+----------+--------------------------+
| 1 | SIMPLE | record_updates | index | idx_marctoxctransformation_record_updates_date_updated | idx_marctoxctransformation_record_updates_date_updated | 9 | NULL | 11772117 | Using where; Using index |
+----+-------------+----------------+-------+--------------------------------------------------------+--------------------------------------------------------+---------+------+----------+--------------------------+
devuser@xcmst > mysql --user=user --password=pass -D marctoxctransformation -e "show keys from record_updates"
+----------------+------------+--------------------------------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+----------------+------------+--------------------------------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
| record_updates | 1 | idx_marctoxctransformation_record_updates_date_updated | 1 | date_updated | A | 2416 | NULL | NULL | YES | BTREE | |
| record_updates | 1 | idx_marctoxctransformation_record_updates_record_id | 1 | record_id | A | 11772117 | NULL | NULL | YES | BTREE | |
+----------------+------------+--------------------------------------------------------+--------------+--------------+-----------+-------------+----------+--------+------+------------+---------+
Run Code Online (Sandbox Code Playgroud)
更新 - 我的解决方案在这里:http: //code.google.com/p/xcmetadataservicestoolkit/wiki/ResumptionToken
Bre*_*ley 21
如果mysql必须计算11M行,那么加速简单计数真的没有多少办法.至少不要让它达到低于1秒的速度.你应该重新考虑如何计算.一些想法:
向表中添加自动增量字段.它看起来你不会从表中删除,所以你可以使用简单的数学来找到记录计数.选择初始较早日期的最小自动增量编号和后一日期的最大值,并从另一个中减去一个以获得记录计数.例如:
SELECT min(incr_id) min_id FROM record_updates WHERE date_updated BETWEEN '2009-10-11 15:33:22' AND '2009-10-12 23:59:59';
SELECT max(incr_id) max_id FROM record_updates WHERE date_updated > DATE_SUB(NOW(), INTERVAL 2 DAY);`
Run Code Online (Sandbox Code Playgroud)创建另一个表,总结每天的记录数.然后,您可以查询该表以获取总记录.每年只有365条记录.如果您需要更精细的时间,请查询摘要表中的整天,并查询当前表,仅查看开始日和结束日的记录计数.然后将它们全部加在一起.
如果数据没有改变,它看起来不像,那么汇总表将易于维护和更新.它们将大大加快速度.
由于>'2009-10-11 15:33:22'包含了大部分记录,
我建议做一个反向匹配<'2009-10-11 15:33:22'(mysql工作越少越好,涉及的行越少)
select
TABLE_ROWS -
(select count(*) from record_updates where add_date<"2009-10-11 15:33:22")
from information_schema.tables
where table_schema = "marctoxctransformation" and table_name="record_updates"
Run Code Online (Sandbox Code Playgroud)
你可以结合编程语言(比如bash shell)
来使这个计算更聪明......
例如先做执行计划来计算哪个比较会使用较小的行
根据我的测试(大约10M记录),正常比较大约需要3秒,
现在减少到大约0.25 秒
由于版本控制,MySQL 不会“优化”InnoDB 中的 count(*) 查询。索引中的每个项目都必须进行迭代和检查,以确保版本正确显示(例如,不是开放提交)。由于可以在数据库中修改任何数据,因此范围选择和缓存将不起作用。但是,您可以通过使用触发器来实现。这种疯狂有两种方法。
第一种方法存在减慢事务速度的风险,因为它们都不能真正并行运行:使用插入后和删除后触发器来递增/递减计数器表。第二个技巧:使用这些插入/删除触发器来调用存储过程,该存储过程将输入到外部程序中,该外部程序类似地向上和向下调整值,或者对非事务表进行操作。请注意,如果发生回滚,这将导致数字不准确。
如果您不需要确切的数字,请查看此查询:
select table_rows from information_schema.tables
where table_name = 'foo';
Run Code Online (Sandbox Code Playgroud)
差异示例:count(*): 1876668,table_rows: 1899004。table_rows 值是一个估计值,即使数据库没有更改,每次也会得到不同的数字。
出于我自己的好奇心:您需要每秒更新的确切数字吗?如果是这样,为什么?
您应该在“date_updated”字段上添加索引。
如果您不介意更改表的结构,您可以做的另一件事是使用“int”格式的日期时间戳而不是“datetime”格式,而且它可能会更快。如果您决定这样做,查询将是
select count(date_updated) from record_updates where date_updated > 1291911807
Run Code Online (Sandbox Code Playgroud)