sql垃圾收集vs清理php中的查询

时间:2017-05-22 00:08:26

标签: php mysql collections duplicates garbage

所以,我制作了一个生成以下SQL查询的php脚本:

SELECT * FROM icecream WHERE 
flavor = 'vanilla' AND color = 'purple' AND (quality = 'aaa') 
OR flavor = 'marzipan' AND color = 'purple' AND (quality = 'aaa')  
OR flavor = 'vanilla' AND color = 'purple' AND (quality = 'aaa') 

查询的最后一位和第一位是相同的。

我看起来不对,显然我更喜欢运行像

这样的查询
SELECT * FROM icecream WHERE 
flavor = 'vanilla' AND color = 'purple' AND (quality = 'aaa') 
OR flavor = 'marzipan' AND color = 'purple' AND (quality = 'aaa')

省略最后一行。

在这个例子中看起来很好,但让我们说  1.可能有23个“OR味道......”部分  2. 100种不同口味  3. 50种不同的颜色  4. 20种不同的质量等级。

突然间,如果没有对相同数据的重复请求,创建漂亮的SQL查询会变得更加复杂。

当前的SQL查询有效。但是我应该清理查询以消除重复,还是应该将它留给SQL引擎来为我做?

我的意思是,我能做到......但值得吗?一方面,我想传递干净的SQL查询,但另一方面,似乎这些事情是SQL引擎真正想要做的事情。

有什么建议吗?

2 个答案:

答案 0 :(得分:2)

您可以使用EXPLAIN [EXTENDED] SELECT ...阅读MySQL优化器创建的查询计划来回答您的问题。如果计划相同,那么服务器不仅会将您的查询视为逻辑上等效,而且还会将它们内部减少到相同的查询。

https://dev.mysql.com/doc/refman/5.7/en/explain.html

您的偏好应该是生成的查询在逻辑上是最优的,而不是做可以减少优化器可用选项的事情(通过在WHERE中使用列名作为函数参数进行不良操作,并且是眼球可调试的。没有必要聪明。

(a = 1 AND b = 1 AND c = 5) OR
(a = 1 AND b = 1 AND c = 27)

......完全等同于......

(a = 1 AND b = 1) AND (c = 5 OR c = 27)

...或...

(a = 1 AND b = 1 AND c IN (5,27))

...并且优化器将很容易理解这些条件,无论它们在查询中如何表达。生成的计划应该是相同的,因此在生成动态查询时不需要优先于其他计划。 (较早版本的MySQL可能不一定处理过最后一个版本,因为它们可能已经处理了前两个版本,但现在这不应该是一个问题。)

重要的是,WHERE当然是一个逻辑表达式,从逻辑角度来看具有确定性的评估优先级,但这与对每行的评估顺序不同......理论上,没有顺序其中对最终表达式的条件的评估是有序的 - 但是优化器可以自由实际以任何看似正确和最优的顺序评估条件,而不管它们如何表达。

基于索引查找,此处可能会选择查找所有b = 1行,然后在该集合中查找c = 5 OR c = 27,最后扫描结果行以查找a = 1条件。如果列(b,c)上有一个索引,则可能就是这种情况。程序意义上没有捷径 - WHERE a = 1 AND b = 1在逻辑上与WHERE b = 1 AND a = 1相同。

请注意,您应该在示例查询中使用更多括号,以便AND / OR优先级的分组是明确的。当然,服务器会正​​确使用它,但是眼球更容易被欺骗,并且使眼球明确无误的括号对MySQL优化器没有任何损害,这似乎很喜欢它们。

答案 1 :(得分:1)

好的,我看到的问题是:

1)SQL引擎会删除重复吗?

  

这些东西是SQL引擎真正要做的事情

2)如何在不费力的情况下传递干净的查询?

  

我想传递干净的SQL查询

SQL是声明性语言。

A declarative language表示您告诉它该做什么,它决定了如何做。

在这种情况下,mysql引擎将接受您的查询并确定如何检索您的数据。作为此过程的一部分,查询解析器应删除查询中的重复项。 (解析器可能不会删除它们,这将取决于查询的复杂性和适当的优化)。这样做的缺点是稍微长一点的解析,虽然我不认为延迟是显而易见的,特别是在一个包含许多where子句的复杂查询中。

您的php脚本似乎专注于低级别的抽象。

我最好的猜测是你的脚本获取一些数据并将其转换为字符串,然后通过转换重复,并使用下一段数据。

此方法的缺点是修改或调整结果对象。转换器不知道在先前步骤中发生了什么,并且不能容易地检测和移除重复的行。你需要做的是有一些对象可以帮助采取一些规则并从中构建一个SQL查询。 (其中一个工具是Zend Db)。

最后,我只想指出,您尝试制作的查询似乎不必要地复杂。

  

23“或味道......”部分

当然,虽然您可能需要进行如此复杂的查询,但复杂查询会有更多可能会影响性能的区域。检查您要完成的任务并确定是否有更直接的方法来获取它可能更为谨慎。目前我没有足够的信息来确定是否有其他方式。