MySQL Query在服务器上运行缓慢但在VM运行速度很快

时间:2015-03-13 15:59:21

标签: mysql

我遇到的问题是,在分配了4GB的VirtualBox机器上查询时间不到一秒,但在16GB的实际服务器上查询时间超过20秒。

首先,这是架构的相关部分:

accounts (about 13k records)
(
    act_id
)

contacts (about 13k records)
(
    cnt_id,
    cnt_description,
    cnt_hascontact_id,
    cnt_hascontact_type
)

addresses (about 13k records)
(
    add_id,
    add_description,
    add_hasaddress_id,
    add_hasaddress_type
)

以下是我正在运行的查询:

SELECT 
    act_id, 
    act_name, 
    act_short, 
    act_ptnumber, 
    cnt_firstname, 
    cnt_lastname, 
    cnt_phone, 
    cnt_email, 
    add_street1, 
    add_city, 
    add_state, 
    add_zip 
FROM accounts  
INNER JOIN addresses ON act_id = add_hasaddress_id  
INNER JOIN contacts ON act_id = cnt_hascontact_id
WHERE act_name LIKE '%<some string>%'
AND cnt_description = 1
AND add_description = 3
GROUP BY act_id
LIMIT 100;

现在。联系人和地址表是多态的,因此除了accounts.act_id之外,这里没有索引。我认为这很重要,但同样,我的VM只需不到一秒的时间来运行查询。

我打开了每台机器上的分析,发现在真实服务器上花了这么长时间才能复制到tmp table&#39;。这可能需要20秒。我觉得奇怪的是VM服务器甚至不执行这一步骤。所以,我明白为什么它会这么快。

当然,真正的服务器正在使用中,因此数据库一次被大约100个左右的用户所击中,而我的VM只运行我的查询。我尝试增加&t; tmp_table_size&#39;的值。和&#39; max_heap_table_size&#39;至1024M,但没有做任何事情。

有没有人知道发生了什么或我如何解决这个问题?提前感谢您的帮助。

编辑:

所有表格都是InnoDB

一些conf:

VM:

tmpdir                               = /var/lib/mysqltmp
table-definition-cache               = 4096
table-open-cache                     = 4096
max-connections                      = 400
max-connect-errors                   = 1000000
max-allowed-packet                   = 16M
skip-name-resolve
wait-timeout                         = 600
key-buffer-size                      = 32M
myisam-sort-buffer-size              = 128M
innodb-file-format                   = Barracuda

服务器:

tmpdir                          = /var/lib/mysqltmp
skip-name-resolve
sql-mode                        = NO_ENGINE_SUBSTITUTION
table-open-cache                = 4096
table-definition-cache          = 4048
tmp-table-size                  = 2048M
max-heap-table-size             = 2048M
back-log                        = 100
max-connect-errors              = 10000
max-allowed-packet              = 64M
interactive-timeout             = 3600
wait-timeout                    = 600
default-storage-engine          = InnoDB
innodb                          = FORCE
key-buffer-size                 = 64M
myisam-sort-buffer-size         = 128M

如果配置不存在则默认为

编辑2:

这是每台服务器上查询的 EXPLAIN SELECT

VM:

1   SIMPLE  contacts    ref contacts_cnt_description_foreign    contacts_cnt_description_foreign    4   const   5724    Using temporary; Using filesort
1   SIMPLE  accounts    eq_ref  PRIMARY,accounts_act_name_unique,accounts_act_type_foreign,accounts_act_businesstype_foreign,accounts_act_parent_foreign    PRIMARY 4   supportnet.contacts.cnt_hascontact_id   1   Using where
1   SIMPLE  addresses   ALL addresses_add_description_foreign               12548   Using where; Using join buffer (Block Nested Loop)

服务器:

1   SIMPLE  contacts    ref contacts_cnt_description_foreign    contacts_cnt_description_foreign    4   const   6155    Using temporary; Using filesort
1   SIMPLE  addresses   ALL addresses_add_description_foreign               12903   Using where; Using join buffer
1   SIMPLE  accounts    eq_ref  PRIMARY PRIMARY 4   supportnet.contacts.cnt_hascontact_id   1   Using where

3 个答案:

答案 0 :(得分:0)

InnoDB - 很好。但我没有看到innodb_buffer_pool_size的设置。这很重要,应该是可用 RAM的70%左右。由于RAM不同,并且您可能使用不同的版本(具有不同的默认值),请查看SHOW VARIABLES LIKE 'innodb%';还有其他重要设置可能会有不同的默认设置。

如果生产计算机上正在运行其他查询,则可能会破坏缓存(buffer_pool)。这可能会导致你看到的。如果还有其他&#34;大&#34;查询,让我们关注它们。

数据集的大小和内容是否相同?

不要使用RAM磁盘 - 备用空间在buffer_pool中更有用。而且,如果你的查询过于庞大,它就会崩溃。

  

&#39; tmp_table_size的&#39;和&#39; max_heap_table_size&#39;到1024M

这很危险!它可能导致RAM耗尽,这会导致交换&#34;对于性能而言, 更糟糕,而不是将它们设置得更低。

编辑(基于EXPLAINs)

添加INDEX(add_hasaddress_id) - 请注意ALL进入addresses后如何说SHOW CREATE TABLE?这意味着没有索引是有用的。如果还有其他问题,请向我们提供{{1}}。

答案 1 :(得分:0)

每张表中的记录如此之少,如果你忘记了索引,就不可能花20秒钟。您应该检查锁,防火墙堵塞或网络问题等内容

答案 2 :(得分:0)

最终的解决方案最终是升级mysql。一旦我从5.5移动到5.6,这个问题就消失了。