如何优化 select 300.000 行的 MySQL 代码 +
How to optimize MySQLl code that select for 300.000 rows +
我需要为包含 300k+ 条记录的 table 创建 XML 个文件。
代码大约需要 3~4 秒才能完成(这是 acceptable 吗?)。
再加上 MySQL 的数据检索,大约需要 32 秒才能完成(这是接受 table 吗?):
查询
SELECT `id`, `join_at`
FROM girls g
WHERE g.del_flg = 0
ORDER BY g.join_at, g.id ASC
如果我 运行 来自 navicat mysql 的这个单一查询它仍然需要大约 20 秒。
我尝试了什么:
起初,select查询没有成功,因为“内存耗尽”错误(php.ini - memory_limit = 128M)
之后我将memory_limit
改为-1。但是我看到很多人说把 memory_limit
改成 -1
不好
那么如何针对 300k+ 记录优化 select
查询:
仅使用 PHP、sql、DOMDocument 代码
将 #1 中的选项与数据库中的索引列结合使用
你还知道什么...
PHP 代码 SQL 查询:
public function getInfo() {
MySQL::connect();
try {
$select = 'SELECT `id`, `join_at`';
$sql = ' FROM girls g';
$sql .= ' WHERE g.del_flg = 0';
$sql .= ' ORDER BY g.join_at, g.id ASC';
$sql = sprintf($sql, $this->table);
MySQL::$sth = MySQL::$pdo->prepare($select . $sql);
MySQL::$sth->execute();
while($rows = MySQL::$sth->fetch(\PDO::FETCH_ASSOC)) {
$values[] = array('id' => $rows['id'], 'join_at' => $rows['join_at']);
}
// $rows = MySQL::$sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (\PDOException $e) {
return null;
}
return $values;
}
我发现 ORDER BY g.join_at, g.id ASC
部分会影响执行时间。当我删除它并使用 PHP 代替排序时,执行时间从总计约 50 秒减少到约 5 秒。
另一件事是,如果我将 memory_limit
设置为 128M,则会导致“内存耗尽”错误(512M 可以)。这个问题还有其他解决方案吗?
这是我目前在 table:
上的索引
排序最好在数据库端完成。但是您需要定义适当的索引。 order by
在您的情况下很昂贵。尽管您在 del_flg
上有一个可以阻止 table 扫描的索引,但它无法产生所需的输出顺序。
所以我建议更改索引 del_flg
你必须包含更多字段:
DROP INDEX del_flg ON girls;
CREATE INDEX del_flg ON girls (del_flg, join_at, id);
如果这不能缩短执行时间,则创建一个不包含 del_flag
:
的索引
CREATE INDEX join_at ON girls (join_at, id);
我需要为包含 300k+ 条记录的 table 创建 XML 个文件。
代码大约需要 3~4 秒才能完成(这是 acceptable 吗?)。
再加上 MySQL 的数据检索,大约需要 32 秒才能完成(这是接受 table 吗?):
查询
SELECT `id`, `join_at`
FROM girls g
WHERE g.del_flg = 0
ORDER BY g.join_at, g.id ASC
如果我 运行 来自 navicat mysql 的这个单一查询它仍然需要大约 20 秒。
我尝试了什么:
起初,select查询没有成功,因为“内存耗尽”错误(php.ini - memory_limit = 128M)
之后我将
不好memory_limit
改为-1。但是我看到很多人说把memory_limit
改成 -1
那么如何针对 300k+ 记录优化 select
查询:
仅使用 PHP、sql、DOMDocument 代码
将 #1 中的选项与数据库中的索引列结合使用
你还知道什么...
PHP 代码 SQL 查询:
public function getInfo() {
MySQL::connect();
try {
$select = 'SELECT `id`, `join_at`';
$sql = ' FROM girls g';
$sql .= ' WHERE g.del_flg = 0';
$sql .= ' ORDER BY g.join_at, g.id ASC';
$sql = sprintf($sql, $this->table);
MySQL::$sth = MySQL::$pdo->prepare($select . $sql);
MySQL::$sth->execute();
while($rows = MySQL::$sth->fetch(\PDO::FETCH_ASSOC)) {
$values[] = array('id' => $rows['id'], 'join_at' => $rows['join_at']);
}
// $rows = MySQL::$sth->fetchAll(\PDO::FETCH_ASSOC);
} catch (\PDOException $e) {
return null;
}
return $values;
}
我发现 ORDER BY g.join_at, g.id ASC
部分会影响执行时间。当我删除它并使用 PHP 代替排序时,执行时间从总计约 50 秒减少到约 5 秒。
另一件事是,如果我将 memory_limit
设置为 128M,则会导致“内存耗尽”错误(512M 可以)。这个问题还有其他解决方案吗?
这是我目前在 table:
上的索引排序最好在数据库端完成。但是您需要定义适当的索引。 order by
在您的情况下很昂贵。尽管您在 del_flg
上有一个可以阻止 table 扫描的索引,但它无法产生所需的输出顺序。
所以我建议更改索引 del_flg
你必须包含更多字段:
DROP INDEX del_flg ON girls;
CREATE INDEX del_flg ON girls (del_flg, join_at, id);
如果这不能缩短执行时间,则创建一个不包含 del_flag
:
CREATE INDEX join_at ON girls (join_at, id);