【发布时间】:2013-09-06 02:50:13
【问题描述】:
我正在尝试减少此脚本的执行时间。它在一个循环中查询大约 1000 次大约 200 万条记录的数据库:
foreach ($ids as $id){
$stmt=$dbh->query("SELECT SQL_CACHE * FROM `ids`
WHERE $id BETWEEN `id_start` AND `id_end`");
$rows[] = $stmt->fetch();
}
在 4 核 8 GB 机器上需要很长时间(大约 800 秒!)。 id 组不重叠,id 在每次执行中往往来自几个不同的组,我已经索引了 (id_start,id_end) 和 (id_end)。
缓存极大地改善了这种情况(多次运行相同的 1000 个值只需几秒钟),但我想知道如何加快非缓存查询的速度。
EXPLAIN 的示例输出:
"id" "select_type" "table" "type" "possible_keys" "key" "key_len" "ref" "rows" "Extra"
"1" "SIMPLE" "ids" "range" "id_start,id_end" "id_start,id_end" "5" "" "52508" "Using index condition"
编辑:有时我得到“使用位置”而不是“使用索引条件”(不确定,但我认为来自高于 840771583 的 id 值)为什么?
编辑 2:完整的创建代码:
CREATE TABLE `ids` (
`id_start` INT(10) UNSIGNED NULL DEFAULT NULL,
`id_end` INT(10) UNSIGNED NULL DEFAULT NULL,
`iso-639-1` VARCHAR(2) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`country_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`region_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`city_name` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`area_code` VARCHAR(16) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
`timezone` VARCHAR(6) NULL DEFAULT NULL COLLATE 'utf8_unicode_ci',
UNIQUE INDEX `id_startid_end` (`id_start`, `id_end`),
INDEX `id_end` (`id_end`),
INDEX `country_name` (`country_name`),
INDEX `region_name` (`region_name`),
INDEX `city_name` (`city_name`),
INDEX `area_code` (`area_code`),
INDEX `iso-639-1` (`iso-639-1`),
INDEX `timezone` (`timezone`)
)
COLLATE='utf8_unicode_ci'
ENGINE=InnoDB;
【问题讨论】:
-
EXPLAIN对查询有何看法?它使用索引吗? -
@Barmar 是的,看起来确实如此。我编辑添加了
EXPLAIN的输出。 -
这个表是只读表吗?假设“读/写拆分”。它使用哪种存储引擎?
-
您真的应该在循环之外准备查询并将
$id绑定为参数。一条语句执行多次总是更好 -
间隔
(id_start,id_end)是否重叠,即查询是否有可能返回多行?如果它们不重叠,请在此处查看我的答案,在一个几乎相同的问题中:Slow Query Gets Even Slower After Indexing