为什么相同的查询解释&在从属MySQL服务器上执行的方式与主服务器不同?

时间:2016-02-12 12:02:55

标签: mysql indexing database-replication

我有一个主MySQL服务器和一个从服务器。数据在它们之间复制。

当我在主人身上运行此查询时,需要花费数小时;在奴隶上需要几秒钟。 EXPLAIN计划重新计算 - 奴隶检查的行数远远少于主人。

但是,由于这两个数据库中的结构和数据完全相同(或者至少应该是这样),并且它们都运行相同版本的MySQL(5.5.31 Enterprise),所以我不会&#39了解造成这种情况的原因。

这是与this question(和其他人)类似的症状,但我不认为它是相同的根本原因,因为我的两台服务器通过MySQL复制同步,结构和数据内容是(或应该是)相同的,OS&两台服务器上的硬件资源完全相同 - 它们是VMWare,另一台是另一台服务器的映像。

我已经验证了两个服务器上每个表中的行数完全相同,并且它们的配置是相同的(除了具有指向主服务器的指令的从服务器)。如果没有通过数据本身来查看是否存在任何差异,我不确定我还能检查什么,并且会对任何建议表示感谢。

查询

 SELECT COUNT(DISTINCT(cds.company_id))
 FROM   jobsmanager.companies c
 ,      jobsmanager.company_jobsmanager_settings cjs
 ,      jobsmanager.company_details_snapshot cds
 ,      vacancies v
 WHERE  c.company_id = cjs.company_id
 AND    cds.company_id = c.company_id
 AND    cds.company_id = v.jobsmanager_company_id
 AND    cjs.is_post_a_job = 'Y'
 AND    cjs.can_access_jobsmanager = 'Y'
 AND    cjs.account_status != 'suspended'
 AND    v.last_live BETWEEN cds.record_date - INTERVAL 365 DAY AND cds.record_date
 AND    cds.record_date BETWEEN '2016-01-30' AND '2016-02-05';

大师解释如下,驾驶台上300万行,没有按键使用,并且需要一个多小时才能返回结果:

+----+-------------+-------+--------+-------------------------+----------------+---------+---------------------------------+---------+--------------------------+
| id | select_type | table | type   | possible_keys           | key            | key_len | ref                             | rows    | Extra                    |
+----+-------------+-------+--------+-------------------------+----------------+---------+---------------------------------+---------+--------------------------+
|  1 | SIMPLE      | v     | ALL    | job_owner,last_live_idx | NULL           | NULL    | NULL                            | 3465433 |                          |
|  1 | SIMPLE      | c     | eq_ref | PRIMARY                 | PRIMARY        | 4       | s1jobs.v.jobsmanager_company_id |       1 | Using where; Using index |
|  1 | SIMPLE      | cds   | ref    | PRIMARY,company_id_idx  | company_id_idx | 4       | jobsmanager.c.company_id        |     538 | Using where              |
|  1 | SIMPLE      | cjs   | eq_ref | PRIMARY,qidx,qidx2      | PRIMARY        | 4       | jobsmanager.c.company_id        |       1 | Using where              |
+----+-------------+-------+--------+-------------------------+----------------+---------+---------------------------------+---------+--------------------------+

奴隶使用不同的驱动表,使用索引,预测更多像检查的310,000行,并在几秒钟内返回结果:

+----+-------------+-------+--------+-------------------------+-----------+---------+----------------------------+--------+--------------------------+
| id | select_type | table | type   | possible_keys           | key       | key_len | ref                        | rows   | Extra                    |
+----+-------------+-------+--------+-------------------------+-----------+---------+----------------------------+--------+--------------------------+
|  1 | SIMPLE      | cds   | range  | PRIMARY,company_id_idx  | PRIMARY   | 3       | NULL                       | 310381 | Using where; Using index |
|  1 | SIMPLE      | c     | eq_ref | PRIMARY                 | PRIMARY   | 4       | jobsmanager.cds.company_id |      1 | Using index              |
|  1 | SIMPLE      | cjs   | eq_ref | PRIMARY,qidx,qidx2      | PRIMARY   | 4       | jobsmanager.c.company_id   |      1 | Using where              |
|  1 | SIMPLE      | v     | ref    | job_owner,last_live_idx | job_owner | 2       | jobsmanager.cds.company_id |     32 | Using where              |
+----+-------------+-------+--------+-------------------------+-----------+---------+----------------------------+--------+--------------------------+

我在两台服务器上都运行了ANALYZE TABLE,OPTIMIZE TABLE和REPAIR TABLE ... QUICK,试图让它们保持一致,没有运气。

作为临时解决方案,我可以在奴隶上运行查询,因为他们在cron脚本中,即使他们在奴隶上花了很长时间,他们也不会像他们那样增加主人的负担当他们在主人身上跑时但是,我很感激任何其他信息,说明为什么这些不同或我还能检查/修改哪些可以解释两者之间如此巨大的差异。我唯一能找到的是奴隶有更多的免费内存,因为它很少使用;那个人会解释这个吗?如果不是其他什么?

$ ssh s1-mysql-01 free # master
             total       used       free     shared    buffers     cached
Mem:      99018464   98204624     813840          0     160752   55060632
-/+ buffers/cache:   42983240   56035224
Swap:      4095992    4095992          0
$ ssh s1-mysql-02 free # slave
             total       used       free     shared    buffers     cached
Mem:      99018464   80866420   18152044          0     224772   72575168
-/+ buffers/cache:    8066480   90951984
Swap:      4095992     206056    3889936
$

非常感谢。

1 个答案:

答案 0 :(得分:1)

2解释的唯一真正的巨大差异是,在主人的空缺表上没有使用索引。

您可以尝试将index hint(强制索引)放入主数据库中以强制使用job_owner索引。

您还可以尝试在master上的上述查询中涉及的所有表上运行analyze table,以确保更新表和索引统计信息。