如何让MySQL利用可用的系统资源,或找到“真正的问题”?

时间:2010-06-11 14:05:21

标签: mysql

这是在SuSE Enterprise 10上运行的MySQL 5.0.26服务器。这可能是Serverfault问题。

使用这些特定查询的网络用户界面(如下所示)有时会显示 30 + ,甚至最多120 + ,以生成相关页面。

在开发时,当查询单独运行时,它们在第一次运行时最多需要20秒(没有启用查询缓存)但在此之后的2到7秒内 - 我假设因为所涉及的表和索引已经放入公羊。

据我所知,最长的加载时间是由读取/更新锁定引起的。这些是 MyISAM 表。所以它似乎是一个长时间的更新,然后是几秒钟的查询,他们只是加起来。我对这个解释很好。

我不喜欢的是 MySQL似乎没有使用它上面的硬件,虽然瓶颈似乎是数据库,我无法理解为什么

我会说“扔更多的硬件”,但我们做了并且它似乎没有改变这种情况。在最慢的时间内查看“顶部”从未显示mysqld的cpu或内存利用率,好像服务器完全没有问题 - 但是,为什么查询需要这么长时间?

如何让MySQL使用这个硬件的废话,或者找出我做错了什么?

额外详情:

在MySQL Administrator(适用于Windows)的“内存运行状况”选项卡上,密钥缓冲区的使用率不到1/8 - 因此所有索引都应该在RAM中。我可以提供任何可能有用的图表的屏幕截图。

迫切需要解决这个问题。可以这么说,有遗留代码“生成”这些查询,而且它们几乎就像它们一样。我已经尝试了所涉及的表的每个索引组合,但欢迎任何建议。

以下是开发中的当前Create Table语句(我添加的'实验'键,似乎仅为示例查询帮助一点):

CREATE TABLE `registration_task` (                                                       
    `id` varchar(36) NOT NULL default '',                                                  
    `date_entered` datetime NOT NULL default '0000-00-00 00:00:00',                        
    `date_modified` datetime NOT NULL default '0000-00-00 00:00:00',                       
    `assigned_user_id` varchar(36) default NULL,                                           
    `modified_user_id` varchar(36) default NULL,                                           
    `created_by` varchar(36) default NULL,                                                 
    `name` varchar(80) NOT NULL default '',                                                
    `status` varchar(255) default NULL,                                                    
    `date_due` date default NULL,                                                          
    `time_due` time default NULL,                                                          
    `date_start` date default NULL,                                                        
    `time_start` time default NULL,                                                        
    `parent_id` varchar(36) NOT NULL default '',                                           
    `priority` varchar(255) NOT NULL default '9',                                          
    `description` text,                                                                    
    `order_number` int(11) default '1',                                                    
    `task_number` int(11) default NULL,                                                    
    `depends_on_id` varchar(36) default NULL,                                              
    `milestone_flag` varchar(255) default NULL,                                            
    `estimated_effort` int(11) default NULL,                                               
    `actual_effort` int(11) default NULL,                                                  
    `utilization` int(11) default '100',                                                   
    `percent_complete` int(11) default '0',                                                
    `deleted` tinyint(1) NOT NULL default '0',                                             
    `wf_task_id` varchar(36) default '0',                                                  
    `reg_field` varchar(8) default '',                                                     
    `date_offset` int(11) default '0',                                                     
    `date_source` varchar(10) default '',                                                  
    `date_completed` date default '0000-00-00',                                            
    `completed_id` varchar(36) default NULL,                                               
    `original_name` varchar(80) default NULL,                                              
    PRIMARY KEY  (`id`),                                                                   
    KEY `idx_reg_task_p` (`deleted`,`parent_id`),                                          
    KEY `By_Assignee` (`assigned_user_id`,`deleted`),                                      
    KEY `status_assignee` (`status`,`deleted`),                                            
    KEY `experimental` (`deleted`,`status`,`assigned_user_id`,`parent_id`,`date_due`)  
    ) ENGINE=MyISAM DEFAULT CHARSET=latin1   

有问题的荒谬查询之一:

SELECT 
    users.user_name   
    assigned_user_name, 
    registration.FIELD001 parent_name, 
    registration_task.status status,
    registration_task.date_modified date_modified,
    registration_task.date_due date_due, 
    registration.FIELD240 assigned_wf,
    if(LENGTH(registration_task.description)>0,1,0) has_description,
    registration_task.* 
FROM 
    registration_task LEFT JOIN users ON registration_task.assigned_user_id=users.id 
    LEFT JOIN registration ON registration_task.parent_id=registration.id 
where 
    (registration_task.status != 'Completed' AND registration.FIELD001 LIKE '%' 
       AND registration_task.name LIKE '%' AND registration.FIELD060 LIKE 'GN001472%') 
    AND  registration_task.deleted=0  
ORDER BY date_due asc LIMIT 0,20;

my.cnf - '[mysqld]'部分。

[mysqld]
port = 3306
socket  = /var/lib/mysql/mysql.sock
skip-locking
key_buffer = 384M
max_allowed_packet = 100M
table_cache = 2048 
sort_buffer_size = 2M 
net_buffer_length = 100M 
read_buffer_size = 2M 
read_rnd_buffer_size = 160M 
myisam_sort_buffer_size = 128M
query_cache_size = 16M
query_cache_limit = 1M

EXPLAIN以上查询,没有附加索引

       
+----+-------------+-------------------+--------+--------------------------------+----------------+---------+------------------------------------------------+---------+-----------------------------+
| id | select_type | table             | type   | possible_keys                  | key            | key_len | ref                                            | rows    | Extra                       |
+----+-------------+-------------------+--------+--------------------------------+----------------+---------+------------------------------------------------+---------+-----------------------------+
|  1 | SIMPLE      | registration_task | ref    | idx_reg_task_p,status_assignee | idx_reg_task_p | 1       | const                                          | 1067354 | Using where; Using filesort |
|  1 | SIMPLE      | registration      | eq_ref | PRIMARY,gbl                    | PRIMARY        | 8       | sugarcrm401.registration_task.parent_id        |       1 | Using where                 |
|  1 | SIMPLE      | users             | ref    | PRIMARY                        | PRIMARY        | 38      | sugarcrm401.registration_task.assigned_user_id |       1 |                             |
+----+-------------+-------------------+--------+--------------------------------+----------------+---------+------------------------------------------------+---------+-----------------------------+

EXPLAIN以上查询,带有'experimental'索引:

       
+----+-------------+-------------------+--------+-----------------------------------------------------------+------------------+---------+------------------------------------------------+--------+-----------------------------+
| id | select_type | table             | type   | possible_keys                                             | key              | key_len | ref                                            | rows   | Extra                       |
+----+-------------+-------------------+--------+-----------------------------------------------------------+------------------+---------+------------------------------------------------+--------+-----------------------------+
|  1 | SIMPLE      | registration_task | range  | idx_reg_task_p,status_assignee,NewIndex1,tcg_experimental | tcg_experimental | 259     | NULL                                           | 103345 | Using where; Using filesort |
|  1 | SIMPLE      | registration      | eq_ref | PRIMARY,gbl                                               | PRIMARY          | 8       | sugarcrm401.registration_task.parent_id        |      1 | Using where                 |
|  1 | SIMPLE      | users             | ref    | PRIMARY                                                   | PRIMARY          | 38      | sugarcrm401.registration_task.assigned_user_id |      1 |                             |
+----+-------------+-------------------+--------+-----------------------------------------------------------+------------------+---------+------------------------------------------------+--------+-----------------------------+

显示来自registration_task的索引;

mysql> SHOW INDEXES FROM registration_task;
+-------------------+------------+------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+
| Table             | Non_unique | Key_name         | Seq_in_index | Column_name      | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
+-------------------+------------+------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+
| registration_task |          0 | PRIMARY          |            1 | id               | A         |     1445612 |     NULL | NULL   |      | BTREE      |         |
| registration_task |          1 | idx_reg_task_p   |            1 | deleted          | A         |           2 |     NULL | NULL   |      | BTREE      |         |
| registration_task |          1 | idx_reg_task_p   |            2 | parent_id        | A         |       57824 |     NULL | NULL   |      | BTREE      |         |
| registration_task |          1 | By_Assignee      |            1 | assigned_user_id | A         |        5295 |     NULL | NULL   | YES  | BTREE      |         |
| registration_task |          1 | By_Assignee      |            2 | deleted          | A         |        5334 |     NULL | NULL   |      | BTREE      |         |
| registration_task |          1 | status_assignee  |            1 | status           | A         |          18 |     NULL | NULL   | YES  | BTREE      |         |
| registration_task |          1 | status_assignee  |            2 | deleted          | A         |          23 |     NULL | NULL   |      | BTREE      |         |
| registration_task |          1 | NewIndex1        |            1 | deleted          | A         |           2 |     NULL | NULL   |      | BTREE      |         |
| registration_task |          1 | NewIndex1        |            2 | assigned_user_id | A         |        5334 |     NULL | NULL   | YES  | BTREE      |         |
| registration_task |          1 | NewIndex1        |            3 | parent_id        | A         |      180701 |     NULL | NULL   |      | BTREE      |         |
| registration_task |          1 | tcg_experimental |            1 | date_due         | A         |        1919 |     NULL | NULL   | YES  | BTREE      |         |
| registration_task |          1 | tcg_experimental |            2 | deleted          | A         |        3191 |     NULL | NULL   |      | BTREE      |         |
| registration_task |          1 | tcg_experimental |            3 | status           | A         |        8503 |     NULL | NULL   | YES  | BTREE      |         |
| registration_task |          1 | tcg_experimental |            4 | assigned_user_id | A         |       53541 |     NULL | NULL   | YES  | BTREE      |         |
| registration_task |          1 | tcg_experimental |            5 | parent_id        | A         |      722806 |     NULL | NULL   |      | BTREE      |         |
+-------------------+------------+------------------+--------------+------------------+-----------+-------------+----------+--------+------+------------+---------+

15 rows in set (0.00 sec)

解?

我想我可能已经解决了这个问题,对某些人来说似乎如此令人尴尬地显而易见,但直到现在才被忽略:registration.id的定义是:

`id` bigint(20) unsigned NOT NULL auto_increment

registration_task.parent_id(FK到registration.id)是:

`parent_id` varchar(36) NOT NULL

通过以下方式更改此内容:

alter table `sugarcrm401`.`registration_task` change `parent_id` `parent_id` bigint(20) UNSIGNED NOT NULL;

...导致EXPLAIN仅显示检查的 25 行,其中早期 651,903 103,345 最好强制执行疯狂索引。

如果我发布了registration表的表定义,我相信有人可能已经发现了它。我将在周末之后验证这一点并发布后续信息。

4 个答案:

答案 0 :(得分:1)

当你有一个查询说!=它总是会很慢。请注意,即使状态字段位于两个不同的索引上,索引也没有在查询的那一部分上使用!

您不希望将varchar(255)字段完全编入索引,并将其作为两个不同键的一部分,这将使您的更新非常慢。总共有五个索引只会增加混乱。如果您在更新发生的同一时刻进行任何选择,那么您需要花费很长时间才能看到更新。

您可能想要做的只是索引255个字符字段的一小部分。更好的是,您可能希望在此处使用整数(statusCode)而不是status。这会加速很多事情。

拥有更多内存或更多CPU在这里无济于事。有一个额外的硬盘驱动器可以提高20 - 30%的速度。但是,只需重新组织索引,就可以在不到一秒的时间内完成相同的查询。

答案 1 :(得分:1)

您应该能够使用适当的索引对其进行优化。正如FractalizeR所说,你需要连接列的索引和Where语句中的列。只将它们全部添加到一个索引将无法解决您的问题。您在注册时有哪些索引?

答案 2 :(得分:0)

请在表格中发布SHOW INDEXES结果。我现在可以给出的通用建议是:

  • 在registration_task字段中添加单独的索引:assigned_user_id,parent_id,date_due
  • 在注册时添加索引.FIELD060
  • 删除部分查询“AND registration.FIELD001 LIKE'%'和registration_task.name LIKE'%'” - 它没用。 %表示任何数量的任何字符

之后请再次发布EXPLAIN。

答案 3 :(得分:0)

大部分问题的答案都在我的编辑中发布:

registration.id的定义是:

`id` bigint(20) unsigned NOT NULL auto_increment

registration_task.parent_id(FK到registration.id)是:

`parent_id` varchar(36) NOT NULL

通过以下方式更改此内容:

alter table `sugarcrm401`.`registration_task` change `parent_id` `parent_id` bigint(20) UNSIGNED NOT NULL;

...导致EXPLAIN仅显示检查的 25 行,其中早期 651,903 103,345 最好强制执行疯狂索引。

如果我发布了registration表的表定义,我相信有人可能已经发现了它。


然而,这并没有完全解决问题。我确定我遗漏了一些细节,但这个项目在这一点上远远落后于我。非常感谢您的所有时间和答案!