【发布时间】:2015-05-16 04:52:10
【问题描述】:
我遇到的问题是,在分配了 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 表”。这本身可能需要 20 秒。我觉得奇怪的是虚拟机服务器甚至没有执行这一步。所以,我明白为什么它要快得多了。
当然,真正的服务器正在使用中,因此数据库一次会受到大约 100 个左右的用户的访问,而我的虚拟机则只运行我的查询。我尝试将 'tmp_table_size' 和 'max_heap_table_size' 的值增加到 1024M,但这没有任何作用。
有没有人知道发生了什么或者我该如何解决这个问题?提前感谢您的帮助。
编辑:
所有表都是 InnoDB
一些配置:
虚拟机:
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:
虚拟机:
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
【问题讨论】:
-
您是否考虑过从 RAM 磁盘运行 MySQL 中的 tmp 表?这是一篇不错的文章:2bits.com/articles/… 另一件事是启用和使用查询缓存?
-
在测试速度时,使用
SELECT SQL_NO_CACHE ...确保查询缓存不满足您的查询。 -
存储引擎,存储引擎配置?没有提到那些?
-
您到底在寻找什么数据?数据库使用 InnoDB。我添加了一些相关的配置信息。
标签: mysql