为动态选择索引多列的最佳方法

时间:2012-04-17 19:01:57

标签: mysql indexing

基本上我有一个包含大约7亿行的表,每天不断更新大约20万到30万行,每个月结束,我将删除超过3个月的数据。

CREATE TABLE TESTRECORD (
  TIMEADDED timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  SERIAL varchar(8) NOT NULL,
  ENDTIME varchar(14) NOT NULL,
  MODEL varchar(2) NOT NULL,
  PROCESS int(4) NOT NULL,
  PF varchar(4) NOT NULL,
  COMID varchar(6) NOT NULL,
  COMTP varchar(3) NOT NULL,
  TRIAL varchar(4) NOT NULL,
  TEST varchar(8) NOT NULL,
  SECTION int(2) NOT NULL,
  DATA_0 float NOT NULL,
  DATA_1 float NOT NULL,
  DATA_2 float NOT NULL,
  DATA_3 float NOT NULL,
  DATA_4 float NOT NULL,
  DATA_5 float NOT NULL,
  PRIMARY KEY (SN,ENDTIME,SECTION),
  UNIQUE KEY BASESN (SN,ENDTIME,MODEL,PROCESS,PF,COMID,TRIAL,TEST,SECTION),
  KEY COMID (COMID),
  KEY TRIAL (TRIAL),
  KEY PF (PF),
  KEY TEST (TEST)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

唯一键定义了将在select语句中使用的参数。 由于此表的基本功能是用于动态数据分析,因此没有特定的命令将在where子句中发生什么以及将使用多少个,并且可能有一些随机分组由一个或两个cols组成。从独特的钥匙。因此,几乎不可能将所有可能的组合编入索引,以确保在任何给定选择上快速操作。

根据我的理解,mysql根据它们在模式中列出的顺序使用索引,所以在我的情况下,如果我在select语句中使用SN,ENDTIME和PF,则只使用唯一键中的前2列。有没有什么有效的方法可以打破索引,如每列1个索引或查询技术,以加快速度,或者至少在where子句的不同组合列中实现基本相同的性能?

提前非常感谢〜!!!

3 个答案:

答案 0 :(得分:2)

MySQL中的索引就像您在书末可能找到的索引一样。如果您正在寻找“意大利辣香肠比萨饼”的食谱,您首先要查找意大利辣香肠,然后再查看披萨。如果您正在寻找“披萨”,那么该指数对您没有帮助,因为披萨在指数中是次要的意大利辣香肠 - 如果您先查看意大利辣香肠,您只能找到披萨。这就是列X,Y的索引如何工作。如果您计划按顺序在列X和Y上运行查询,那么将两列上的索引放在一起是有意义的。如果你想在X上运行查询和在Y上运行查询,那么复合索引就没有多大意义了!

我建议您坐下来定义最常运行的查询类型,并分析您的存储和处理能力。索引可占用大量空间,尤其是在数百万行中工作时。索引是存储空间和处理能力之间的经典折衷,没有人不熟悉您的数据库可以告诉您针对您的特定情况的索引的最佳数量或配置。

还要查看每列中存储的唯一值的数量。与Oracle不同,MySQL不支持标准表的位图样式索引(它使用B-Tree)。除了技术细节之外,这意味着在具有相对较少的唯一值的列上构建索引将不会为您提供每单位索引空间的尽可能多的值。

最后要注意的是,对于某些类型的数据分析,您可能需要考虑将一些数据导出到MEMORY表。 MEMORY表基本上是临时表,可以跨用户会话保存它们的结构。当您使用它们或发生崩溃时,它们会丢失数据,但不会丢失它们的结构。内存表支持HASH索引,这些索引散列索引列的值以加速数据检索。在大多数情况下,它们非常快,并且在正确使用时可以显着提高性能。

如果您真的对数据库优化感兴趣,我建议您查看“高性能MySQL”一书。

答案 1 :(得分:1)

我建议您考虑使用不同的存储,例如基于列的存储引擎,例如infobright开源分析数据库。它基于mysql架构,就像使用mysql一样,除了面向大数据和分析查询。 www.infobright.org

答案 2 :(得分:0)

任何表的解决方案:

SELECT 
  CONCAT(
    'ALTER TABLE ', 
    TABLE_NAME, 
    ' ', 
    'ADD ', 
    IF(
      NON_UNIQUE = 1, 
      CASE UPPER(INDEX_TYPE) WHEN 'FULLTEXT' THEN 'FULLTEXT INDEX' WHEN 'SPATIAL' THEN 'SPATIAL INDEX' ELSE CONCAT(
        'INDEX ', INDEX_NAME, ' USING ', INDEX_TYPE
      ) END, 
      IF(
        UPPER(INDEX_NAME) = 'PRIMARY', 
        CONCAT(
          'PRIMARY KEY USING ', INDEX_TYPE
        ), 
        CONCAT(
          'UNIQUE INDEX ', INDEX_NAME, ' USING ', 
          INDEX_TYPE
        )
      )
    ), 
    '(', 
    GROUP_CONCAT(
      DISTINCT CONCAT('', COLUMN_NAME, '') 
      ORDER BY 
        SEQ_IN_INDEX ASC SEPARATOR ', '
    ), 
    ');'
  ) AS 'Show_Add_Indexes' 
FROM 
  information_schema.STATISTICS 
WHERE 
  TABLE_SCHEMA = 'your_database' 
  and TABLE_NAME = 'your_table';
-- GROUP BY 
--   TABLE_NAME, 
--   INDEX_NAME 
-- ORDER BY 
--   TABLE_NAME ASC, 
--   INDEX_NAME ASC;