通过大量连接提高MySQL查询速度

通过大量连接提高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

我在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_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
设置或类似设置)而严重不足

检查事项:

  • 使用
    hdparm-Tt/dev/sdX
    测试驱动器性能-SSD磁盘或RAID阵列可能损坏
  • 检查您的性能设置。请毫不犹豫地将所有
    缓冲区
    设置置于
    my.cnf
    中,至少是其当前值的两倍,您有可用的RAM。一些可能需要极高的设置。类似这样的脚本可能对此有所帮助
还要检查问题是否可在另一台服务器上复制

提升MySQL缓冲区值的一个良好开端是将此位添加到您的
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%的问题会严重影响操作系统的性能。这实际上可能会给您带来性能问题,您不应该尝试“保存”交换空间。