2

所以基本上我有一个包含大约 7 亿行的表,并且每天不断更新大约 200k-300k 行,每个月底,我都会清除超过 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 子句中的不同列组合中实现大致相同的性能?

提前非常感谢~!!!

4

3 回答 3

2

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

我建议您坐下来定义最常运行的查询类型,并分析您的存储和处理能力。索引会占用大量空间,尤其是在处理数百万行时。索引是存储空间和处理能力之间的经典权衡,不熟悉您的数据库的任何人都无法告诉您针对特定情况的最佳索引数量或配置是多少。

还要查看存储在每列中的唯一值的数量。MySQL 与 Oracle 不同,不支持标准表的位图样式索引(它使用 B-Tree)。抛开技术细节不谈,这意味着在唯一值数量相对较少的列上构建索引不会像您想象的那样为您提供每单位索引空间的价值。

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

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

于 2012-04-17T19:22:30.850 回答
1

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

于 2012-04-17T19:17:17.847 回答
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;
于 2021-02-05T12:44:23.757 回答