我有一个MySQL InnoDB表,该表使用每天的表结构(一个表存储每天的数据)。每个表由50列组成(此表无法归一化,因为该表用于存储每个表大约有1600万行的CDR数据(与电信相关)。
这是表模式:
CREATE TABLE IF NOT EXISTS <tableName_2018_07_08> (
<col1> int(4) NOT NULL,
<col2> timestamp NOT NULL,
<col3> varchar(255) NOT NULL,
<col4> int(4) NOT NULL,
<col5> varchar(255) NOT NULL,
<col6> varchar(255),
<col7> varchar(255),
<col8> varchar(255),
<col9> varchar(255),
<col10> varchar(255),
<col11> varchar(255),
<col12> varchar(255),
<col13> varchar(255),
<col14> varchar(255),
<col15> varchar(255),
<col16> varchar(255),
<col17> varchar(255),
<col18> varchar(255),
<col19> varchar(255),
<col20> varchar(255),
<col21> varchar(255),
<col22> varchar(255),
<col23> varchar(255),
<col24> varchar(255),
<col25> varchar(255),
<col26> varchar(255),
<col27> varchar(255),
<col28> varchar(255),
<col29> varchar(255),
<col30> varchar(255),
<col31> varchar(255),
<col32> varchar(255),
<col33> varchar(255),
<col34> varchar(255),
<col35> varchar(255),
<col36> varchar(255),
<col37> varchar(255),
<col38> varchar(255),
<col39> varchar(255),
<col40> varchar(255),
<col41> varchar(255),
<col42> varchar(255),
<col43> varchar(255),
<col44> varchar(255),
<col45> varchar(255),
<col46> varchar(255),
<col47> varchar(255),
<col48> varchar(255),
<col49> varchar(255),
<col50> varchar(255),
PRIMARY KEY (<col1>, <col2>, <col3>, <col4>, <col5>)
) ROW_FORMAT=COMPACT ENGINE=InnoDB;
在查询的where子句中使用4个字段。
select
cast(<col1> as char),
<col2>,
<col3>,
cast(<col4> as char),
<col5>,
<col6>,
<col6>,
<col7>,
<col8>,
<col9>,
<col10>,
<col11>,
<col12>,
<col13>,
<col14>,
<col15>,
<col16>,
<col16>,
<col17>,
<col18>,
<col19>,
<col20>,
<col21>,
<col22>,
<col23>,
<col24>,
<col25>,
<col26>,
<col27>,
<col28>,
<col29>,
<col30>,
<col31>,
<col32>,
<col33>,
<col34>,
<col35>,
<col36>,
<col37>,
<col38>,
<col39>,
<col40>
FROM
<tabele_2018_03_03>
WHERE
col2 >= '2018-07-01 00:00:00' AND
col2 <= '2018-07-01 02:00:00' AND
col3 = 'Test01' AND col4 = '11'
时间和时间是从前端发送的,并且只有当这些过滤器是从前端发送时,才会添加另外三个过滤器。
此查询需要5分钟以上才能完成,这是一个问题。由于这仅适用于一天,并且只要前端发送以获取数据多天,它将花费超过10分钟的时间。
答案 0 :(得分:0)
记忆?还是Innodb?内存易失;除登台外,请勿使用MEMORY。
每天都有桌子-通常设计不好。
“添加了更多过滤器”-让我们来看一下。您提供的查询的任何解决方案在其他情况下可能都无济于事。
您要2个小时再加上1秒?检查范围测试。
cast(event as char)
-不必要;即使没有cast
,输出也无法与字符串区分开。
如果没有以cdr_timestamp
开头的索引 ,该查询将不得不搜索整个表。添加索引可能无济于事,因为查询可能只查看表的2/24。
归一化 和 。当然,数据以字符串形式输入,但是在存储在“事实”表中之前,应转换更多的列。 这将需要一两个额外的步骤。参见http://mysql.rjweb.org/doc.php/staging_table
该链接提供了一些技巧,可以帮助您-您每秒插入约200行,接近限制,无需采取额外步骤;这为您提供了一些步骤。它提供了一种2-SQL规范化技术来非常有效地做到这一点。如果您的某些查询是“摘要报告”,那么它会研究如何使它们更快。等等
即使对这么多列盲目使用(255)
也会带来很大的性能负担。
通过使用适当的数据类型以及规范化,将大大减少磁盘占用空间,从而提供更高的性能。
PRIMARY KEY
的5列-太多了。那是唯一标识行的最小列组合吗?
百万行的输出将如何处理?您不能使用MySQL来汇总/压缩/任何数据吗? 5分钟对于查找和挖掘那么多数据并不是没有道理的!
reserved...
-从长远来看,您可能会发现,挥霍不是做事情的最佳方法。
研究从每一列中获取的值,以查看它们是否值得标准化。并查看(对于字符串)什么长度更有意义:
SELECT COUNT(*) AS total_rows,
COUNT(DISTINCT vas_type) AS distinct values,
MAX(CHAR_LENGTH(vas_type)) AS longest
FROM tbl;
如果distinct_values / total_rows> 40%,请进行归一化(选择临界值)。
在longest
中使用VARCHAR(...)
,加上一个软键。
除非有必要使用utf8,否则请使用CHARACTER SET latin1
。