2012-01-27 117 views
1

我有一个简单的10M行的MYSQL表。它需要优化,但我不确定为什么这个简单的选择需要这么长时间。在流式传输结果出现之前,这似乎就像查询时间。没有WHERE子句的SQL查询优化

安装性能调整的任何好链接?非常过时例如:http://www.mysqlperformanceblog.com/2006/09/29/what-to-tune-in-mysql-server-after-installation/

##QUERY: 
SELECT * FROM scga_results; 

mysql-slow.log 
# Time: 120126 15:05:03 
# [email protected]: abc[abc] @ localhost [] 
# Query_time: 25 Lock_time: 0 Rows_sent: 11896464 Rows_examined: 11896464 
select * from scga_results; 

##REF 
mysql> describe scga_results; 
+--------------+------------------+------+-----+-------------------+----------------+ 
| Field  | Type    | Null | Key | Default   | Extra   | 
+--------------+------------------+------+-----+-------------------+----------------+ 
| id   | int(10) unsigned | NO | PRI | NULL    | auto_increment | 
| application | varchar(255)  | NO | MUL |     |    | 
| field  | varchar(255)  | YES |  | NULL    |    | 
| value  | varchar(255)  | YES |  | NULL    |    | 
| period  | varchar(255)  | YES | MUL | NULL    |    | 
| end_time  | varchar(255)  | YES |  | NULL    |    | 
| date_updated | timestamp  | NO |  | CURRENT_TIMESTAMP |    | 
+--------------+------------------+------+-----+-------------------+----------------+ 
7 rows in set (0.00 sec) 

mysql> show table status like 'scga_results'\G 
*************************** 1. row *************************** 
      Name: scga_results 
     Engine: MyISAM 
     Version: 10 
    Row_format: Dynamic 
      Rows: 11897025 
Avg_row_length: 96 
    Data_length: 1152314616 
Max_data_length: 281474976710655 
    Index_length: 180028416 
     Data_free: 0 
Auto_increment: 11971193 
    Create_time: 2012-01-26 13:32:57 
    Update_time: 2012-01-27 00:20:04 
    Check_time: 2012-01-26 13:39:19 
     Collation: latin1_swedish_ci 
     Checksum: NULL 
Create_options: 
     Comment: 
1 row in set (0.00 sec) 

添加查询详细信息

USES KEY: 
mysql> explain select * from scga_results where application="20000"; 
+----+-------------+--------------+------+---------------+---------+---------+-------+------+-------------+ 
| id | select_type | table  | type | possible_keys | key  | key_len | ref | rows | Extra  | 
+----+-------------+--------------+------+---------------+---------+---------+-------+------+-------------+ 
| 1 | SIMPLE  | scga_results | ref | index_2  | index_2 | 257  | const | 1 | Using where | 
+----+-------------+--------------+------+---------------+---------+---------+-------+------+-------------+ 
1 row in set (0.26 sec) 

NO KEY USED: 
mysql> explain select * from scga_results where id="20"; 
mysql> explain select * from scga_results where period="day"; 
mysql> explain select * from scga_results where application>0; 

添加轮廓细节

mysql> SET PROFILING=1; 
mysql> SELECT * FROM scga_results; 

------------------+---------------------+ 
11897787 rows in set (23.05 sec) 

mysql> show profiles; 
+----------+-------------+-----------------------------+ 
| Query_ID | Duration | Query      | 
+----------+-------------+-----------------------------+ 
|  1 | 6.72981800 | select id from scga_results | 
|  2 | 23.06871000 | select * from scga_results | 
+----------+-------------+-----------------------------+ 
2 rows in set (0.00 sec) 

mysql> SHOW PROFILE FOR QUERY 2; 
+--------------------------------+-----------+ 
| Status       | Duration | 
+--------------------------------+-----------+ 
| (initialization)    | 0.000008 | 
| checking query cache for query | 0.000047 | 
| checking permissions   | 0.00001 | 
| Opening tables     | 0.000013 | 
| System lock     | 0.000007 | 
| Table lock      | 0.000026 | 
| init       | 0.000023 | 
| optimizing      | 0.000006 | 
| statistics      | 0.000015 | 
| preparing      | 0.000013 | 
| executing      | 0.000004 | 
| Sending data     | 23.055196 | 
| end       | 0.000018 | 
| query end      | 0.000007 | 
| freeing items     | 0.000014 | 
| closing tables     | 0.000009 | 
| logging slow query    | 0.013294 | 
+--------------------------------+-----------+ 
17 rows in set (0.01 sec) 
+1

如果没有'WHERE'子句,则迫使数据库遍历整个数据集(10M行)。如果磁盘速度较慢,则可能需要25秒。 – Chris 2012-01-27 19:56:34

+0

这不是一个简单的选择,而是一个最糟糕的选择。它执行全表扫描,从磁盘读取所有页面。如果您不提供索引字段的条件,您将得到错误的查询时间。必须收集表统计信息并重建索引等...... – 2012-01-27 20:02:21

+0

“应用程序”列是varchar,您运行的是WHERE应用程序> 0? – 2012-01-27 21:30:29

回答

3

它看起来像您检索更多然后1GB的数据。如果你真的需要更快的数据,我认为你将需要硬件的改变。

由于服务器上的其他负载,您的查询可能比您想要的运行速度慢,但您很可能已达到硬件可以提供的限制。

您可以尝试切换到更快的硬盘驱动器,某些类型的RAID硬盘驱动器或某种固态存储器,甚至将表格转换为MEMORY表格,以便将其保存在RAM中。请记住,由于数据必须通过内存总线等,所以这仍然不会使其成为瞬时数据。

+0

这必须是MySQL中的设计缺陷或调优问题。简单的'SELECT * FROM table'需要30秒才能运行,然后再返回流结果。不应该有任何表扫描或解释?会改变--min-examine-row-limit强制MySQL发送结果/跳过表扫描? – celeryandsprite 2012-01-27 21:05:09

+0

@Nick:如果你想要所有的行,那么所有的行都必须从表中读取(通常在磁盘中)。这是一个表扫描。 – 2012-01-27 21:31:57

+0

@ypercube我不能相信在发送任何消息之前MySQL会读取所有结果?我现在已经运行了一个[优化脚本](http://www.day32.com/MySQL/)并阅读了一些内容:http://dev.mysql.com/doc/refman/5.0/en/memory- use.html。性能:在阅读$ top时显示cpu为%65,内存为0.3%。发送cpu 7%,内存58%。我的桌子会变大...... – celeryandsprite 2012-01-27 23:27:48