需要帮助简化SQL查询以避免WHERE和SELECT中的冗余数学运算

时间:2011-03-18 19:46:52

标签: mysql sql where-clause

*大家好,我正在进行查询,并且不确定如何尽可能快地进行查询并尽可能减少冗余。我真的希望那里有人可以帮我提出一个很好的方法。

提前感谢您的帮助!*

好的,所以这就是我最好的解释。我简化了表格和数学,以便了解我想要了解的内容。

基本上我有一个永远不会改变的小表,并且总是只有这样的50k记录:

Values_Table

ID      Value1     Value2
1          2           7
2          2           7.2
3          3           7.5
4          33          10
….50000     44       17.2

并且有几张表不断变化并且相当大,例如可能有多达500万条记录:

Flags_Table

Index      Flag1    Type
1           0       0
2             0       1
3             1       0
4            1       1
….5,000,000 1       1

Users_Table

Index           Name       ASSOCIATED_ID
1               John           1
2               John           1
3               Paul           3
4               Paul           3
….5,000,000 Richard         2

我需要将所有3张桌子绑在一起。从小表中可能返回的最多结果是在100个结果附近。大型表在索引上连接,然后将这些表连接到Values_Table ON Values_Table.ID = Users_Table.ASSOCIATED_ID ....那部分很容易。

对我来说棘手的是我需要尽快返回一个限制为10个结果的列表,其中value1和value2以数学方式操作以返回new_值,其中new_value小于10且结果按new_value排序,我需要的任何其他语句都可以应用于标志。我确实需要能够沿着极限移动。 EG LIMIT 0,10 / 11,10 / 21,10等......

在后续(或相同的可能)查询中,我需要在应用限制之前获得与该条件匹配的所有类型的前10个计数。

所以例如我想加入所有这些并返回Value1 + Value2< 10我还需要点数。

所以我想要的是:

Index      Name           Flag1 New_Value
1           John           0           9
2           John           0           9
5000000 Richard         1           9.2

第二个回应是:

ID (not index)      Count
    1                  2
    2                  1

我尝试了几种方法,最终提出了以下有点难看的问题:

SELECT INDEX, NAME, Flag1, (Value1 * some_variable + Value2) as New_Value
FROM Values_Table
JOIN Users_Table ON ASSOCIATED_ID = ID
JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE (Value1 * some_variable + Value1) < 10
ORDER BY New_Value
LIMIT 0,10

然后计算:

SELECT ID, COUNT(TYPE) as Count, (Value1 * some_variable + Value2) as New_Value
FROM Values_Table
JOIN Users_Table ON ASSOCIATED_ID = ID
JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE (Value1 * some_variable + Value1) < 10
GROUP BY TYPE
ORDER BY New_Value
LIMIT 0,10

能够在我的WHERE子句中过滤不同的标志是很重要的;这可能听起来很愚蠢,但我提到,因为我可以看到一个更快的方法是使用HAVING语句,但我不相信这将在某些情况下工作取决于我想要使用我的WHERE子句过滤。

使用标记表进行过滤时:

SELECT INDEX, NAME, Flag1, (Value1 * some_variable + Value2) as New_Value
FROM Values_Table
JOIN Users_Table ON ASSOCIATED_ID = ID
JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE (Value1 * some_variable + Value1) < 10 AND Flag1 = 0
ORDER BY New_Value
LIMIT 0,10

...过滤计数:

SELECT ID, COUNT(TYPE) as Count, (Value1 * some_variable + Value2) as New_Value
FROM Values_Table
JOIN Users_Table ON ASSOCIATED_ID = ID
JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE (Value1 * some_variable + Value1) < 10 AND Flag1 = 0
GROUP BY TYPE
ORDER BY New_Value
LIMIT 0,10

工作正常但必须为每一行多次运行数学运算,我感到唠叨的感觉是它还在Values_table表的同一行上多次运行数学运算。我的想法是,我应该首先只获取Values_table的有效响应,然后将这些响应连接到其他表以减少处理; SQL如何优化,但我不确定它是否可能已经这样做了。我知道我可以使用HAVING子句只运行数学一次,如果我这样做,但我不确定我最好如何加入。

我的问题是:

  1. 我可以避免两次运行该数学并仍然使查询工作 (或者我想如果有一个好方法 使第一个也工作 那会很棒)
  2. 最快的方法是什么? 因为这是可以的     经常跑步。
  3. 看起来这应该很简单,但我只是错过了一些愚蠢的东西。

    我打算进入一个临时表,然后将该表连接到自身,但这似乎我会交换数学表针对表进行迭代,但结果仍然很慢。

    感谢大家的帮助,如果我需要澄清一下,请告诉我!

    **为了澄清一个问题,我不能使用预先计算出的值的第3列,因为实际上数学比添加要复杂得多,我只是为了说明而简化它。

3 个答案:

答案 0 :(得分:1)

您是否有基准查询进行比较?通常,尝试超越优化器并不起作用。如果您从一个起始查询中获得了可接受的性能,那么您可以看到正在花费额外工作的位置(由磁盘读取,缓存消耗等指示)并专注于此。

避免诱惑将其分解成碎片并解决它们。这是一个反模式。这尤其包括临时表。

冗余数学通常没问题 - 磁盘活动会带来什么伤害。我从未见过在纯计算中需要减少CPU工作量的查询。

答案 1 :(得分:0)

收集结果并将其放入临时表

SELECT * into TempTable FROM (SELECT INDEX, NAME, Type, ID, Flag1, (Value1 + Value2) as New_Value
               FROM Values_Table
               JOIN Users_Table ON ASSOCIATED_ID = ID
               JOIN Flags_Table ON Flags_Table.Index = Users_Table.Index
WHERE New_Value < 10)
ORDER BY New_Value
LIMIT 0,10

首次查询的返回结果

SELECT INDEX, NAME, Flag1, New_Value 
FROM TempTable

返回类型计数的结果

Select ID, Count(Type)
FROM TempTable
GROUP BY TYPE

答案 2 :(得分:0)

您是否有可能使用预先计算的值将第三列添加到values_table?即使计算结果依赖于其他变量,也可以运行整个表的计算,但只有当这些变量发生变化时才会运行。