MySql单表优化选项

时间:2012-03-03 07:38:32

标签: mysql

我有一个大约有600万行的表,并且有很多列包含大量数据。

我想在此表上实现搜索功能,主要基于创建行时的日期范围和其他一些列。

不需要其他表,因此不存在查询中的联接问题。另外,我在日期列和其他相关列上实现了索引。

如果我搜索大范围,考虑到表格的行数,搜索仍需要很长时间。我已将key_buffer_size增加到1G,并将mysql_query_cache增加到500M。

我想知道是否,

  1. 我还可以做任何其他事情,优化任何可能提高性能的其他变量。
  2. 我应该考虑重新设计表格吗?
  3. 我希望在增加RAM或CPU之前探索所有选项。

    更新

    以下是更多详情

    CPU:Intel Quadcore 内存:4GB 操作系统:CentOS

    +-----------------------------+---------------+------+-----+---------+----------------+
    | Field                       | Type          | Null | Key | Default | Extra          |
    +-----------------------------+---------------+------+-----+---------+----------------+
    | deal_id                     | int(11)       | NO   | PRI | NULL    | auto_increment | 
    | deal_group_id               | int(11)       | NO   | PRI | NULL    |                | 
    | site_id                     | int(11)       | YES  | MUL | NULL    |                | 
    | datetime                    | char(14)      | YES  | MUL | NULL    |                |  
    | deal_category               | varchar(200)  | YES  | MUL | NULL    |                | 
    | vendor_name                 | varchar(200)  | YES  |     | NULL    |                | 
    | area                        | varchar(200)  | YES  | MUL | NULL    |                | 
    | address                     | text          | YES  |     | NULL    |                |  
    | country_code                | varchar(5)    | NO   | MUL | NULL    |                | 
    | expired                     | int(1)        | NO   |     | 0       |                | 
    | type                        | varchar(20)   | NO   |     | REGULAR |                | 
    | pn_id                       | int(11)       | NO   |     | 0       |                | 
    +-----------------------------+---------------+------+-----+---------+----------------+
    

    以上是架构。在where子句中,使用范围datetimedeal_categoryvendor_name in和country_code的组合。所有都被编入索引。以下是一个示例查询

    SELECT distinct t.deal_id, t.deal_group_id, t.site_name, UNIX_TIMESTAMP(t.datetime) as datetime, t.deal_category as deal_category, t.vendor_name, t.area as area, t.country_code FROM table t WHERE 1 AND t.country_code = 'US' AND datetime BETWEEN '20110601' AND '20120303' limit 10;

    我已将innodb_buffer_pool_size增加到大约75%,它提高了某些查询的效果,但如果包含所有过滤器,仍会花费大量时间。

    以下是my.cnf文件设置,

    query_cache_size=500M

    max_allowed_packet= 1G

    innodb_buffer_pool_size = 3G

    key_buffer_size = 1G

    这张桌子非常繁忙,每分钟都有数百封写入。

    希望这能给出更清晰的画面。

    更新更新

    下面是表格中的解释输出和索引,

    +----+-------------+-------+------+-----------------------+--------------+---------+-------+--------+-------------+
    | id | select_type | table | type | possible_keys         | key          | key_len | ref   | rows   | Extra       |
    +----+-------------+-------+------+-----------------------+--------------+---------+-------+--------+-------------+
    |  1 | SIMPLE      | t     | ref  | country_code,datetime | country_code | 17      | const | 521556 | Using where | 
    +----+-------------+-------+------+-----------------------+--------------+---------+-------+--------+-------------+
    

    索引:

    +-------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
    | Table       | Non_unique | Key_name          | Seq_in_index | Column_name   | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment |
    +-------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
    | table       |          0 | PRIMARY           |            1 | deal_id       | A         |     5810775 |     NULL | NULL   |      | BTREE      |         | 
    | table       |          0 | PRIMARY           |            2 | deal_group_id | A         |     5810775 |     NULL | NULL   |      | BTREE      |         | 
    | table       |          1 | site_id           |            1 | site_id       | A         |        2109 |     NULL | NULL   | YES  | BTREE      |        | 
    | table       |          1 | area              |            1 | area          | A         |       18927 |     NULL | NULL   | YES  | BTREE      |         | 
    | table       |          1 | country_code      |            1 | country_code  | A         |          20 |     NULL | NULL   |      | BTREE      |         | 
    | table       |          1 | deal_group_id     |            1 | deal_group_id | A         |     1936925 |     NULL | NULL   |      | BTREE      |         | 
    | table       |          1 | deal_category     |            1 | deal_category | A         |          20 |     NULL | NULL   | YES  | BTREE      |         | 
    | table       |          1 | datetime          |            1 | datetime      | A         |     5810775 |     NULL | NULL   | YES  | BTREE      |         | 
    +-------------+------------+-------------------+--------------+---------------+-----------+-------------+----------+--------+------+------------+---------+
    

    由于

1 个答案:

答案 0 :(得分:3)

  1. 对于运行Innodb的数据库,您需要将innodb_buffer_pool_size的值增加到专用服务器上大约70-80%的可用RAM,以便尽可能多的数据适合内存

  2. 创建一个包含您要在

  3. 上搜索的字段的索引
  4. 使用LIKE%值%搜索不使用索引

  5. 要进行其他调整,您需要提供有关您将要执行的架构和搜索的更多信息

    1. 删除WHERE子句中的“1 AND”比较

    2. 将“20110601”和“20120303”之间的日期时间更改为DATE(日期时间)STR_TO_DATE('20110601','%Y%m%d')和STR_TO_DATE('20120303','%Y%m%)之间的日期时间d')。我假设datetime字段包含MySQL格式的日期

    3. 考虑将日期时间字段从char(14)更改为datetime字段以便更快地进行计算

    4. 如果country_code列只有2位数的国家/地区代码,请考虑将其大小更改为char(2)

    5. 在deal_id列之前删除DISTINCT,这是一个自动增量和主键