在MySQL DBMS中,程序员在编写SQL时是否应该处理查询优化(比如选择最佳的关系代数查询)?或者它是DBMS的责任。
更多地解释我的意思。在这个例子中:
SELECT * FROM Staff s, Branch b
WHERE s.branchNo = b.branchNo AND (s.position = 'Manager' AND b.city = 'London')
MySQL的查询优化器是否有效地决定如何分配谓词的括号(WHERE子句)? (例如,取决于每个表的大小,或系统统计信息中的任何信息)
答案 0 :(得分:1)
这是程序员的责任;这个"责任"无法转移到DBMS。
与MySQL查询优化器看起来一样神秘而神奇,它只是一个计算机程序。它只能做它编程的工作。它没有调用任何"魔法"将低效的SQL查询转换为有效的SQL查询。
作为一个简单示例,请考虑这两个查询(假设dt
是t
中的DATE,DATETIME或TIMESTAMP列):
之一:
SELECT t.foo
FROM t
WHERE t.dt >= '2015-01-05'
AND t.dt < '2015-01-05' + INTERVAL 1 DAY
2:
SELECT t.foo
FROM t
WHERE DATE(t.dt) = '2015-01-05'
这些查询指定相同的结果。使用其中一个查询,MySQL优化器可以选择使用索引范围扫描操作。另一方面,它不能。
程序员有责任&#34;提供允许DBMS有效利用资源的SQL文本。
考虑另一个简单的例子:
SELECT t.foo
FROM t
WHERE t.foo = 'bar'
VS
SELECT s.foo
FROM ( SELECT t.* FROM t ) s
WHERE s.foo = 'bar'
VS
SELECT t.foo
FROM t
HAVING t.foo = 'bar'
这三个查询指定了相同的结果,但是如果我们查看EXPLAIN输出,我们将看到我们没有获得相同的查询计划。
底线:如果我们要在&#34;程序员和#34;之间做出选择。或者&#34;查询优化器&#34;,分配&#34;责任&#34;为了有效地使用资源......从一些简单的例子中可以清楚地看出,查询优化器不能胜任该任务。它只能做它被编程的事情。所以,如果我们必须选择,最终的责任在于程序员。
<强>后续强>
问:在此示例中:
SELECT * FROM Staff s, Branch b WHERE s.branchNo = b.branchNo
AND (s.position = 'Manager' AND b.city = 'London')
MySQL的查询优化器是否有效地决定如何分配谓词的括号(WHERE子句)? (例如,取决于每个表的大小,或系统统计信息中的任何信息)?
答:对于查询优化器,谓词是谓词。谓词周围的多余parens不会混淆优化器。 (您的示例中的parens将被丢弃,他们不会更改查询计划。
赞赏使用表别名。 (这使查询和EXPLAIN输出更短,更容易阅读。)
但是放弃了连接操作的旧式逗号语法。使用JOIN
关键字代替逗号。并将连接谓词移动到ON子句。另外,指定您需要返回的最小列数;请勿返回使用*
并返回您不需要的列。在此示例中,无需同时返回s.branchNo
和b.branchNo
,其中一个可以省略,并使结果集更小。 (指定要返回的列也使DBA能够有效地选择覆盖索引。)
确保您有适当的索引,并查看EXPLAIN输出以了解MySQL将要执行的操作。 (更好的是,使用EXPLAIN EXTENDED和SHOW WARNINGS,以更好地了解MySQL在您的语句中做了什么)
SELECT s.branchNo
, s.position
, b.city
FROM Staff s
JOIN Branch b
ON b.branchNo = s.branchNo
WHERE s.position = 'Manager'
AND b.city = 'London'
作为最佳性能的第一个切入点,我们需要一个索引,该索引具有在WHERE子句中的一个等式谓词中引用的前导列(如果将结果集限制为小于表中10%或20%的行。例如:
... ON Branch (city)
... ON Staff (branchNo, position)
如果我们没有合适的索引,那么MySQL将采用嵌套循环扫描。我们没有注意到小套装上的任何性能问题。但是在较大的套装上,这些操作的效率会低得足以吃掉我们的午餐。
不幸的是,优化器不会自动创建最合适的索引。程序员有责任确保提供合适的索引。
InnoDB存储引擎使统计数据保持最新,它确实做得不错。在MyISAM表上执行ANALYZE TABLE
将确保优化器具有合理的统计数据。
总结一下:我们不能在优化器上抛出一些SQL文本,并希望我们能够从MySQL中获得最佳性能。所以,这个责任最终落在程序员身上。