MySql InnoDB Select查询花费更多时间来生成数据

时间:2018-07-11 05:22:29

标签: mysql innodb database-performance

我有一个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分钟的时间。

1 个答案:

答案 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