我如何提高我的简单mysql查询速度


How can I improve my simple mysql query speed

我有一个非常简单的查询,它一直出现在我缓慢的查询日志中。当它突然出现时,它通常会说查询大约花了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是BTREE
company_users 1 indx_scheduleid 1 scheduleid A 49 'N 'N是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_checked: 0

Query_time: 5 Lock_time: 0 Rows_sent: 0 rows_checked: 0

Query_time: 4 Lock_time: 0 Rows_sent: 1 rows_checked: 1

最后一个是在同一个表上的select。我对select语句进行了分析(因为我不知道如何在Update上进行分析),结果显示:

id select_type表类型possible_keys key key_len ref rows Extra1 SIMPLE company_users const indx_imei indx_imei 22 const 1

拥有大量索引可以加快选择语句的速度,但会减慢插入、更新和删除的速度。我的第一个建议是删除索引并重新执行查询,看看时间是否得到了改善。

我认为,在包含300条记录的平面表上更新一条记录的问题与索引无关。听起来您的插入语句被另一个语句阻塞了。它是总是很慢还是只有在某些条件下才很慢,这将进一步使阻塞看起来是可能的候选人。你需要更多的信息。我会调查表上可能的阻塞选择,看看它们是否是罪魁祸首,并在查看事务隔离级别和自动提交配置之前,先看看这些查询是否可以优化。

如果问题是一个选择查询锁定,您可以通过运行不加锁定的选择查询来验证(并可能解决您的问题)。这可以通过

来完成
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博客有一些有用的见解。

我同意AlexC的说法,很可能是另一个语句阻塞了您的UPDATE语句。如果您想确保您的UPDATES没有被阻塞,您可以使用两个数据库。在主数据库上执行update和insert操作,从第一个数据库复制过来的第二个数据库是所有select操作发生的地方。

或者,你当然可以找出哪些语句实际上阻塞了你的查询,并尝试优化它们。在大量选择的数据库上,这可能不容易实现。