通过大量连接提高MySQL查询速度
我在MySQL中有一个查询,它使用多个连接,目前运行速度很慢,平均运行时间约为35秒 查询是:通过大量连接提高MySQL查询速度,mysql,left-join,database-performance,Mysql,Left Join,Database Performance,我在MySQL中有一个查询,它使用多个连接,目前运行速度很慢,平均运行时间约为35秒 查询是: SELECT t.id, CASE t.emp_accepted WHEN '1' THEN 'No' WHEN '0' THEN 'Yes' END AS accepted, e.department, e.works_id, e.first_name, e.sur_nam
SELECT t.id,
CASE t.emp_accepted
WHEN '1' THEN 'No'
WHEN '0' THEN 'Yes'
END AS accepted,
e.department,
e.works_id,
e.first_name,
e.sur_name,
e.job_title,
e.job_status,
e.site_id,
e.manager,
d1.department_name AS dept_name,
d2.department_name AS sub_dept_name,
temp_hours_worked.hours AS hours,
s.office_name AS site_name,
CONCAT(e2.first_name, ' ', e2.sur_name) AS manager_name,
CONCAT(e3.first_name, ' ', e3.sur_name) AS validated_by
FROM time t
LEFT JOIN employee e
ON t.employee_id = e.employee_id
LEFT JOIN departments d1
ON e.department = d1.id
LEFT JOIN departments d2
ON e.sub_department = d2.id
LEFT JOIN site s
ON e.site_id = s.id
LEFT JOIN employee e2
ON e.manager = e2.id
LEFT JOIN employee e3
ON t.manager_id = e3.id
LEFT JOIN temp_hours_worked
ON temp_hours_worked.week_beginning = t.week_beginning
AND temp_hours_worked.employee_id = t.employee_id
AND temp_hours_worked.company_id=?
WHERE t.company_id = ?;
说明:
+----+-------------+-------------------+--------+---------------+-------------+---------+-----------------------------------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------------+--------+---------------+-------------+---------+-----------------------------------------+------+-------+
| 1 | SIMPLE | t | ref | company_id | company_id | 4 | const | 5566 | |
| 1 | SIMPLE | e | ref | employee_id | employee_id | 4 | DBNAME.t.employee_id | 1 | |
| 1 | SIMPLE | d1 | eq_ref | PRIMARY | PRIMARY | 4 | DBNAME.e.department | 1 | |
| 1 | SIMPLE | d2 | eq_ref | PRIMARY | PRIMARY | 4 | DBNAME.e.sub_department | 1 | |
| 1 | SIMPLE | s | eq_ref | PRIMARY | PRIMARY | 4 | DBNAME.e.site_id | 1 | |
| 1 | SIMPLE | e2 | eq_ref | PRIMARY | PRIMARY | 4 | DBNAME.e.manager | 1 | |
| 1 | SIMPLE | e3 | eq_ref | PRIMARY | PRIMARY | 4 | DBNAME.t.manager_id | 1 | |
| 1 | SIMPLE | temp_hours_worked | ref | company_id | company_id | 4 | const | 5566 | |
+----+-------------+-------------------+--------+---------------+-------------+---------+-----------------------------------------+------+-------+
MySQL版本为5.5.31,在Centos 6.5 64位上运行,服务器为8核4GB RAM,带有SSD磁盘。箱子上的平均载荷为:
load average: 0.24, 0.29, 0.29
可用内存如下所示:
total used free shared buffers cached
Mem: 3880 3067 813 0 177 1065
-/+ buffers/cache: 1825 2055
Swap: 1023 0 1023
磁盘空间正常:
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 45G 11G 32G 26% /
tmpfs 1.9G 0 1.9G 0% /dev/shm
/usr/tmpDSK 1008M 51M 907M 6% /tmp
hdparm-Tt/dev/xvda1的输出
Timing cached reads: 12538 MB in 1.99 seconds = 6297.76 MB/sec
Timing buffered disk reads: 826 MB in 3.00 seconds = 275.27 MB/sec
my.cnf:
[mysql]
# CLIENT #
port = 3306
socket = /var/lib/mysql/mysql.sock
[mysqld]
local-infile=0
# GENERAL #
user = mysql
default_storage_engine = InnoDB
socket = /var/lib/mysql/mysql.sock
pid_file = /var/lib/mysql/mysql.pid
# MyISAM #
key_buffer_size = 32M
myisam_recover = FORCE,BACKUP
# SAFETY #
max_allowed_packet = 16M
max_connect_errors = 1000000
skip_name_resolve
#sql_mode = NO_AUTO_CREATE_USER,NO_AUTO_VALUE_ON_ZERO,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ONLY_FULL_GROUP_BY
sysdate_is_now = 1
innodb = FORCE
#innodb_strict_mode = 1
# DATA STORAGE #
datadir = /var/lib/mysql/
# BINARY LOGGING #
log_bin = /var/lib/mysql/mysql-bin
expire_logs_days = 14
sync_binlog = 1
# CACHES AND LIMITS #
tmp_table_size = 32M
max_heap_table_size = 32M
query_cache_type = 0
query_cache_size = 0
max_connections = 500
thread_cache_size = 50
open_files_limit = 65535
table_definition_cache = 4096
table_open_cache = 4096
# INNODB #
innodb_flush_method = O_DIRECT
innodb_log_files_in_group = 2
innodb_log_file_size = 128M
innodb_flush_log_at_trx_commit = 1
innodb_file_per_table = 1
innodb_buffer_pool_size = 1456M
# LOGGING #
log_error = /var/lib/mysql/mysql-error.log
#log_queries_not_using_indexes = 1
slow_query_log = 1
slow_query_log_file = /var/lib/mysql/mysql-slow.log
被查询/连接的列都是必需的,无法删除,我意识到很多列上都没有索引,但由于它们只是单行,我不确定这是否重要-我还能做些什么来加快查询速度?在这些硬件规格上,此查询永远不会如此缓慢。explain
explain
输出表明,所有连接的字段都使用非常优化的索引,只扫描5566行。唯一的指数改进可能是对临时工作时间
字段周初、员工id、公司id
的综合指数,但这不会有太大的区别。根据解释输出,甚至没有任何文件端口或临时表
我怀疑您可能遇到了锁定问题(您显示的负载很低,但无法说明在这些相同的表上同时运行了多少查询),或者您的MySQL由于配置(使用默认的tiny.config
设置或类似设置)而严重不足
检查事项:
- 使用
测试驱动器性能-SSD磁盘或RAID阵列可能损坏hdparm-Tt/dev/sdX
- 检查您的性能设置。请毫不犹豫地将所有
设置置于缓冲区
中,至少是其当前值的两倍,您有可用的RAM。一些可能需要极高的设置。类似这样的脚本可能对此有所帮助my.cnf
my.cnf
:
key_buffer = 768M
table_cache = 1024
sort_buffer_size = 4M
read_buffer_size = 4M
read_rnd_buffer_size = 16M
myisam_sort_buffer_size = 128M
query_cache_size = 128M
thread_concurrency = 16
table_open_cache = 2048
tmp_table_size = 64M
max_heap_table_size = 64M
您可以查看phpMyAdmin(服务器->变量)中的当前值。索引非常重要。你有没有尝试添加丢失的?为了使连接有效,索引是必要的。顺便说一句,您说服务器有8GB的RAM,但mem输出显示略小于4GB。意外运行32位或错误配置VM?我的输入错误。。。。。我对4GB RAMIs的解释是正确的,您的示例返回了近5566行?你是如何测量时间的?是这样的吗?:我有一个网站,一直等到我的应用程序服务器返回这些结果(它除了将结果写入concole之外什么都不做)?在这种情况下:当涉及到演示时,您是否绝对确定您的客户不是瓶颈?如果在语句中附加一个“limit 100”,会发生什么?不,我进入MySQL客户端,从命令行运行它-我也使用limits运行它,性能差异是非常线性的。我记不起确切的数字,但我做了100、500、1000、2500等,这与总行的相关百分比大致相同。hdparm的输出以及我原始后期制作中my.cnf的内容发生了变化,还有30-35秒就要在命令行上完成了。MySQLTuner警告最大可能内存使用量:8.4G(占已安装RAM的222%)是的,一开始你说有8GB的RAM,对于一个八核服务器来说,4GB稍微有些小,这取决于你想做什么。我还注意到您的交换区域太小了,它应该至少是服务器物理RAM量的1.5倍,最好是2倍。目前,您有25%的问题会严重影响操作系统的性能。这实际上可能会给您带来性能问题,您不应该尝试“保存”交换空间。