我有一个非常简单的查询,在我的慢查询日志中不断出现。当它突然出现时,它通常表示查询大约需要3-6秒。这是查询:
UPDATE company_users
SET isonline=1, last_logon='2011-12-05 19:37:11', last_message=-1,
last_signal=-1, location=-1
WHERE userid='3546600442XXXXX';
我必须使用userid比较,因为这是我在更新时获得的信息。
数据库结构是:
Field Type Null Key Default Extra
id int(11) NO PRI \N auto_increment
userid varchar(20) NO MUL
version varchar(3) YES 37
owneruserid int(11) NO MUL 0
simcard_phonenumber varchar(20) YES \N
registration_date date YES \N
labelname varchar(20) YES \N
isonline smallint(6) YES 0
last_logon datetime YES \N
last_message int(11) YES 0
last_voltage int(11) YES 0
last_reboot datetime YES \N
connect_mode int(11) YES 1
scheduleid int(11) YES MUL -1
location int(11) YES MUL -1
img varchar(50) YES
我有以下索引:
company_users 0 PRIMARY 1 id A 197 \ N \ N BTREE
company_users 1 indx_userid 1 userid A 197 \ N \ N BTREE
company_users 1 indx_location 1 location A 12 \ N \ N YES BTREE
company_users 1 indx_scheduleid 1 scheduleid A 49 \ N \ N YES BTREE
company_users 1 indx_owneruserid 1 owneruserid A 197 \ N \ N BTREE
该表中有大约300行。该数据库与我的网站位于同一服务器上。这些查询使用PHP脚本运行。
希望这足以让我知道我可能做错了什么,或者我可以调整我的配置。
更新: 在Dennis的建议之后,我又看了一下我的慢查询日志,发现在时间范围内记录了三个语句。这是其中两个的信息,它们是上面确定的相同类型的更新语句:
Query_time:5 Lock_time:0 Rows_sent:0 Rows_examined:0
Query_time:5 Lock_time:0 Rows_sent:0 Rows_examined:0
Query_time:4 Lock_time:0 Rows_sent:1 Rows_examined:1
最后一个是同一个桌子上的选择。我对select语句进行了分析(因为我不知道如何在Update上执行此操作)并显示:
id select_type表类型possible_keys键key_len ref rows Extra1 SIMPLE company_users const indx_imei indx_imei 22 const 1
答案 0 :(得分:2)
拥有大量索引可以加快select语句的速度,但会减慢插入,更新和删除的速度。我的第一个建议是删除索引并重新执行查询以查看时间是否得到改善。
答案 1 :(得分:2)
我建议问题是,在300条记录的平面表上更新记录与索引无关。听起来你的insert语句被另一个语句阻止了。只有在某些条件下,它总是缓慢或缓慢,这将进一步使得看起来阻塞是可能的候选者。你真的需要更多的信息。我会调查该表上可能的阻塞选择以查看它们是否是罪魁祸首,并在查看事务隔离级别和自动提交配置之类的事情之前,先查看是否可以优化这些查询。
如果问题是选择查询锁定,则可以通过运行select query而不锁定来验证(并可能解决您的问题)。这可以通过
来完成SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ; -- Place your select query here
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
但是,这种方法有一些与之相关的健康警告。通过使它们尽可能接近最佳而不是使用这种方法,更好地获取有关错误的信息并解决有问题的查询是一种更好的做法。
我记得这个Coding Horror blog有一些有用的见解。
答案 2 :(得分:1)
我同意AlexC,很可能另一个声明是阻止你的UPDATE语句。如果您想确定您的更新没有被阻止,您可以使用两个数据库。在主数据库上,你执行UPDATES和INSERTS,第二个是从第一个复制,是所有SELECTing发生的地方。
或者,您当然可以找出哪些语句实际阻止了您的查询并尝试优化它们。在严重选择的数据库上,这可能不容易实现。