查询性能的最佳实践是什么?
What is the best practice for the Performance of the Query?
关于这个 Table 我使用这个脚本:
$SQL = "
SELECT id, col
FROM t
ORDER BY CASE WHEN 'A B C D E' LIKE CONCAT(col, '%') THEN col END DESC;
";
$stmt = $connect->prepare($SQL);
$stmt->execute();
if ($stmt->rowCount > 0) {
. . PULL_DATA . .
} else {
echo 'No Data Pulled';
}
我用了ORDER BY
因为我想先拉取重要的数据,这是与col相关的任何东西= A B C D E
THEN A B C D
THEN A B C
THEN A B
然后 A
BUT 如果 none 这些 col =
值存在,拉取与这组字符串无关的数据,所以如果 col id 1, 2, 7, 5
我仍然使用其他记录,现在这个查询似乎根本无法优化,所以我考虑了以下使用 WHERE
而不是 ORDER BY
的脚本在 Query:
$SQL = "
SELECT id, col
FROM t
WHERE 'A B C D E' LIKE CONCAT(col, '%')
ORDER BY col DESC;
";
$stmt = $connect->prepare($SQL);
$stmt->execute();
if ($stmt->rowCount > 0) {
. . PULL_DATA . .
} else {
$SQL = "
SELECT id, col
FROM t
ORDER BY col DESC;
";
$stmt = $connect->prepare($SQL);
$stmt->execute();
if ($stmt->rowCount > 0) {
. . PULL_DATA . .
} else {
echo 'No Data Pulled';
}
}
这是保持性能的好方法还是有更好的方法?
为了防止混淆,A B C D E
不是 static 字符串,而是 variable,
而且不总是字母,
它可以是像 Hello My World
这样的词,其中查询按 Hello My World
然后 Hello My
然后 Hello
对值进行排序并且此查询基于此 Question
第一次查询
嗯,查询:
SELECT id, col
FROM t
ORDER BY CASE WHEN 'A B C D E' LIKE CONCAT(col, '%') THEN col END DESC;
选择 table 的所有行。此处无法使用优化,因为 order by
表达式随查询而变化。无法创建对任何订单有帮助的索引。
第二次查询
可以优化第二个查询。如果您知道 col
有最小长度,那么它可以被优化,即使它只有 1 个字符长(希望更长)。
对于此示例,我们假设 col
的最小长度为三个字符。然后我会为这三个头部字符创建一个索引:
alter table t add (col_head as substring(col, 1, 3));
create index ix1_t on t (col_head);
那就加个条件吧,好像是多余的。此额外条件将尝试使用比 Full Table Scan[=41= 快得多的 Index Range Scan table 访问模式]:
SELECT id, col
FROM t
where col_head = substring('A B C D E', 1, 3)
and 'A B C D E' LIKE CONCAT(col, '%')
ORDER BY col DESC;
注1:参数'A B C D E'在SQL中添加了两次。
注2:变更前后,取回MySQL正在使用的执行计划,看是否有差异。检索执行计划 运行:
explain <my_query>
关于这个 Table 我使用这个脚本:
$SQL = "
SELECT id, col
FROM t
ORDER BY CASE WHEN 'A B C D E' LIKE CONCAT(col, '%') THEN col END DESC;
";
$stmt = $connect->prepare($SQL);
$stmt->execute();
if ($stmt->rowCount > 0) {
. . PULL_DATA . .
} else {
echo 'No Data Pulled';
}
我用了ORDER BY
因为我想先拉取重要的数据,这是与col相关的任何东西= A B C D E
THEN A B C D
THEN A B C
THEN A B
然后 A
BUT 如果 none 这些 col =
值存在,拉取与这组字符串无关的数据,所以如果 col id 1, 2, 7, 5
我仍然使用其他记录,现在这个查询似乎根本无法优化,所以我考虑了以下使用 WHERE
而不是 ORDER BY
的脚本在 Query:
$SQL = "
SELECT id, col
FROM t
WHERE 'A B C D E' LIKE CONCAT(col, '%')
ORDER BY col DESC;
";
$stmt = $connect->prepare($SQL);
$stmt->execute();
if ($stmt->rowCount > 0) {
. . PULL_DATA . .
} else {
$SQL = "
SELECT id, col
FROM t
ORDER BY col DESC;
";
$stmt = $connect->prepare($SQL);
$stmt->execute();
if ($stmt->rowCount > 0) {
. . PULL_DATA . .
} else {
echo 'No Data Pulled';
}
}
这是保持性能的好方法还是有更好的方法?
为了防止混淆,A B C D E
不是 static 字符串,而是 variable,
而且不总是字母,
它可以是像 Hello My World
这样的词,其中查询按 Hello My World
然后 Hello My
然后 Hello
对值进行排序并且此查询基于此 Question
第一次查询
嗯,查询:
SELECT id, col
FROM t
ORDER BY CASE WHEN 'A B C D E' LIKE CONCAT(col, '%') THEN col END DESC;
选择 table 的所有行。此处无法使用优化,因为 order by
表达式随查询而变化。无法创建对任何订单有帮助的索引。
第二次查询
可以优化第二个查询。如果您知道 col
有最小长度,那么它可以被优化,即使它只有 1 个字符长(希望更长)。
对于此示例,我们假设 col
的最小长度为三个字符。然后我会为这三个头部字符创建一个索引:
alter table t add (col_head as substring(col, 1, 3));
create index ix1_t on t (col_head);
那就加个条件吧,好像是多余的。此额外条件将尝试使用比 Full Table Scan[=41= 快得多的 Index Range Scan table 访问模式]:
SELECT id, col
FROM t
where col_head = substring('A B C D E', 1, 3)
and 'A B C D E' LIKE CONCAT(col, '%')
ORDER BY col DESC;
注1:参数'A B C D E'在SQL中添加了两次。
注2:变更前后,取回MySQL正在使用的执行计划,看是否有差异。检索执行计划 运行:
explain <my_query>