odbc_exec需要很长时间才能执行简单的查询

时间:2014-01-17 13:08:11

标签: php sql ms-access odbc

我一直在更新php脚本以使用.mdb Access 2010数据库,我发现odbc_exec命令需要很长时间才能执行。我正在运行的SQL查询是:

SELECT MIN(ID) AS fd FROM myTable WHERE ID > 3572 AND ( [field2] LIKE '%TEXT%')
SELECT MAX(ID) AS fd FROM myTable WHERE ID < 3572 AND ( [field2] LIKE '%TEXT%')
SELECT COUNT(*) AS fd FROM myTable WHERE ID <= 3572 AND ( [field2] LIKE '%TEXT%')
SELECT COUNT(*) AS fd FROM myTable WHERE ( [field2] LIKE '%TEXT%')

它们用于我正在更新的搜索结果分页系统。 我的PHP代码是这样的:

$sql = "SELECT MIN(ID) AS fd FROM myTable WHERE ID > 3572 AND ( [field2] LIKE '%TEXT%')"

$sqlconn = odbc_connect("my_data_source","","",SQL_CURSOR_FORWARD_ONLY);
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
// more code using $data

当我运行我的代码时,我发现运行需要几分钟,这太长了。通过评论其后的所有内容,我已经找到了$result = odbc_exec($sqlconn, $sql);行的罪魁祸首。我对php和odbc连接相当新,到目前为止我还没有找到为什么需要这么长时间的原因。直接在数据库上运行查询几乎是即时的。

myTable是数据库中的一个表,包含大约60,000条记录和25列数据。它没有主键字段或我知道的任何索引,但添加主键似乎不会影响运行时间的任何重要数量。

我已经尝试过的一些事情包括将ODBC数据源缓冲区大小从2048增加到4096,在数据库的ID字段上添加主键,并使用SQL_CUR_USE_ODBC游标选项而不是{{1选项。

更新 我不知道这是否相关,但是当我从php文件运行查询时,我发现了一些奇怪的东西。 .mdb数据库位于包含多个其他.mdb数据库的文件夹中,当查询运行时,每个数据库都被锁定(具有附带的.ldb文件)。它也导致Apache运行缓慢。

我不知道要发布的其他相关信息,所以如果有什么我遗失的请告诉我。

1 个答案:

答案 0 :(得分:0)

显然,LIKE '%TEXT%'条件是瓶颈,迫使每个查询进行表扫描。如果每批四个查询的LIKE条件总是相同(即,为同一个记录子集获取四个值),那么使用临时表会有很大帮助。

对于包含60,000条记录的测试表,以下代码需要大约10或11秒才能在我最老和最吱吱作响的测试框上运行:

$sql = "SELECT MIN(ID) AS fd FROM myTable WHERE ID > 3572 AND ( [field2] LIKE '%TEXT%')";
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
$v1 = $data['fd'];

$sql = "SELECT MAX(ID) AS fd FROM myTable WHERE ID < 3572 AND ( [field2] LIKE '%TEXT%')";
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
$v2 = $data['fd'];

$sql = "SELECT COUNT(*) AS fd FROM myTable WHERE ID <= 3572 AND ( [field2] LIKE '%TEXT%')";
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
$v3 = $data['fd'];

$sql = "SELECT COUNT(*) AS fd FROM myTable WHERE ( [field2] LIKE '%TEXT%')";
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
$v4 = $data['fd'];

但是,以下代码在同一台机器上只需1或2秒即可完成:

$tempTableName = uniqid();

$sql = "CREATE TABLE $tempTableName (ID INTEGER PRIMARY KEY)";
$result = odbc_exec($sqlconn, $sql);
$sql = 
        "INSERT INTO $tempTableName (ID) " .
        "SELECT ID FROM myTable WHERE ( [field2] LIKE '%TEXT%')";
$result = odbc_exec($sqlconn, $sql);

$sql = "SELECT MIN(ID) AS fd FROM $tempTableName WHERE ID > 3572";
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
$v1 = $data['fd'];

$sql = "SELECT MAX(ID) AS fd FROM $tempTableName WHERE ID < 3572";
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
$v2 = $data['fd'];

$sql = "SELECT COUNT(*) AS fd FROM $tempTableName WHERE ID <= 3572";
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
$v3 = $data['fd'];

$sql = "SELECT COUNT(*) AS fd FROM $tempTableName";
$result = odbc_exec($sqlconn, $sql);
$data = odbc_fetch_array($result);
odbc_free_result($result);
$v4 = $data['fd'];

$sql = "DROP TABLE $tempTableName";
$result = odbc_exec($sqlconn, $sql);