MySQL通过动态公式提高排序速度

时间:2018-01-21 13:49:18

标签: mysql sorting indexing

我有一个包含多个列的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秒快得多。

这种情况下的瓶颈是什么?

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是一个范围。