我有一个包含多个列的MySQL表和一个基于不同列的效率公式,并根据不同的查询而有所不同。该表包含超过1000万个条目并且是静态的,因此不会添加新条目。
CREATE TABLE `table1` (
`col1` INT(2) UNSIGNED NOT NULL, # this is an ID from another table used as a filter
`col2` INT(5) NOT NULL, # about 20 fixed integer
`col3` INT(1) NULL DEFAULT NULL,
`col4` DECIMAL(4,2) NOT NULL, # fixed decimals -2:0.5:2
`col5` DECIMAL(4,2) NOT NULL, # fixed decimal 5:0.5:10
`col6` INT(2) NOT NULL,
`col7` INT(2) NOT NULL, # fixed integer 0:5:15
`col8` DECIMAL(4,2) NOT NULL, # unknown decimals
`col9` DECIMAL(4,2) NOT NULL, # unknown decimals
`col10` DECIMAL(4,2) NOT NULL, # unknown decimals
`col11` INT(3) NOT NULL, # unknown integer
`col12` DECIMAL(4,2) NOT NULL, # unknown decimals
`col13` DECIMAL(4,2) NOT NULL, # unknown decimals
`col14` DECIMAL(4,2) NOT NULL, # unknown decimals
`col15` DECIMAL(4,2) NOT NULL, # unknown decimals
INDEX `Index1` (`col1`, `col5`, `col4`, `col2`, `col7`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
;
这是两个常见的自动生成查询:
SELECT col6,col5,col2,col3,col13,col14,col7,col1,col11,
col13*col14*col2/col6 AS efficiency
FROM `table1`
WHERE `col1` IN (19,1,2,39,40,34,35)
AND `col5` = '6'
AND col2 >= '1000' AND col2 <= '5600'
AND `col4` = '0'
AND col7 >= 0 AND col7 <= 15
AND col13 >= 3.00 AND col13 <= 4.50
AND col14 >= 0.60
ORDER BY efficiency ASC, col13 ASC
LIMIT 0, 1;
SELECT col6,col5,col2,col3,col8,col9,col10,col11,col12,col7,col1,col8*col10*col2*col9/col6 AS efficiency
FROM `table1`
WHERE `col1` IN (8,11,9,12,16,17,19,24,42,20,43,21,44,22,45,23,25,1,2,3,4,5,28,31,27,39,40,41,34,35)
AND `col5` = '6' AND col2 >= '1000' AND col2 <= '5600'
AND `col4` = '0'
AND col7 >= 0 AND col7 <= 15
AND col8 >= 0.50
AND col9 >= 0.35
AND col10 >= 0.40
AND col11 <= 15
AND col12 >= 0.30
ORDER BY efficiency ASC, col6 DESC
LIMIT 0, 1
第二个查询中包含col1的所有值以强制使用索引
没有ORDER BY子句的查询要快得多。
我有很多这些表,所以总体而言,数据库需要大约65 GB的存储空间。另一个指数会增加所需的空间,对吗?
在没有order and limit子句的情况下处理查询的时间是0,390秒。 (+ 1,922秒。网络,以获得由此产生的几百个条目)。两个条款都需要1,781秒。
因为效率公式有时会有所不同并导致浮点数,所以附加索引似乎是错误的方法。
另一个问题是,我必须第二次对相同的结果进行排序。目前,我只是再次调用查询,这需要(按预期)加倍时间。有没有办法再次对给定结果进行排序?
查询必须在where子句之后处理几百个条目。我认为这应该比2秒快得多。
这种情况下的瓶颈是什么?
答案 0 :(得分:0)
因为效率公式有时会有所不同并导致浮点数,所以附加索引似乎是错误的方法。
一种选择是明确使用索引。为什么效率公式不同?如果你只有一些这样的公式,我建议将它们存储在相同或不同的表中,并在每列上放置一个索引。是的,您可以在浮点数上设置索引。
您可以使用触发器使公式保持最新(在其他数据库中,您可以简单地使用计算列,但MySQL不支持在v8之前的那些)。
查询必须在where子句后处理大约800个条目。
这与30分钟的查询时间不一致,除非您的行真的非常宽。扫描具有数百万行的表应该花费时间,但需要几十秒,而不是几十分钟。如果您可以将条件调整为严格的相等条件(无or
,无in
),则可以使用索引快速查找800个条目。
正如现在所写,除非col2
具有高度选择性,否则索引不会特别有用。
答案 1 :(得分:0)
static
,因此将每种数据类型缩小到最小值。如果这是问题的一部分,这将削减I / O. =
测试哪些列(在您的示例中为col2和col4)。=
列构建各种2列索引。IN
或&#34;范围&#34;中使用的一个更多列来延长其中一些索引。col1*col2/col3 AS efficiency
,那么,好悲伤,把它变成一个专栏。告诉我们您使用的是哪种号码(费用,计费,人数,日期/日期时间等);它可以帮助进一步提供建议。
根据提出的问题细节:
两个查询都将受益于
INDEX(col4, col5, one-other-col) -- where 4 and 5 are in either order
这会将所有=
测试放在索引中。第三列应该是任何可能最具选择性的列。 (当然,这可能是一个猜谜游戏。)
IN
比=
更糟糕,但没有像<
这样的范围(或者像col7). So it is hard to say whether
col1`看到的一对那样有用)索引。
一个&#34;范围&#34;使用了列,优化程序将忽略索引中的任何其他列。因此,在原始索引中,它无法转到col7
,因为col2
是一个范围。