SQL - 进行更新的最快方法

时间:2014-09-12 10:17:04

标签: php mysql sql sql-update

我在PHP / MySQL中创建了一个小程序来更新数据库中的表,我想知道它的性能会如何改变,从而在UPDATE语句中引入一个条件。

现在我正在对表的每条记录执行UPDATE,忽略了我要更新的字段已经计算和更新的事实:

mysql_query("UPDATE matches SET delta=".$delta." WHERE id=".$idp."");

其中$delta是先前计算的PHP变量,id是表的唯一键。

在执行速度方面是否存在差异,插入条件以确定是否已在表中计算/更新增量字段,或者它是否仍设置为0(其默认值)?

mysql_query("UPDATE matches SET delta=".$delta." WHERE id=".$idp." and delta=0");

添加delta=0条件有什么改进吗?

总结我的问题:当由于delta=0条件为假而未执行对表的写操作时,UPDATE是否更快?我的桌子有大约10k的记录。

提前致谢并原谅我可怜的英语! ;-) 安德烈

1 个答案:

答案 0 :(得分:0)

如果你正在做这样的多个更新,那么我通常会建议做一个INSERT而是使用一个重复的键条件来在id已经存在时进行更新。这样,您可能会对表中的每条记录执行单个SQL查询,而不是一个查询。

mysql_query("INSERT INTO matches (id, delta)
VALUES
($idp1, $delta1),
($idp2, $delta2),
($idp3, $delta3),
($idp4, $delta4)
ON DUPLICATE KEY UPDATE delta=VALUES(delta)
");

修改

这是我在执行多个插入/更新时有时会使用的php类(此处有轻度简化版本)

<?php

class table_process
{

    var $link;
    var $row_array = array();
    var $field_name_store = '';
    var $table_name = '';
    var $record_count = 0;
    var $update_clause = '';
    var $rows_to_process = 255;

    function __CONSTRUCT($link, $table_name, $update_clause = '')
    {
        $this->link = $link;
        $this->table_name = $table_name;
        $this->update_clause = $update_clause;
    }
    function __DESTRUCT()
    {
        if (count($this->row_array) > 0)
        {
            $this->process_rows();
        }
    }
    function field_names($in_field_names)
    {
        $this->field_name_store = "(`".implode("`,`", $in_field_names)."`)";
    }
    function record_count()
    {
        return count($this->record_count);
    }
    function make_row($in_row)
    {
        $ret = true;
        foreach($in_row AS &$in_field)
        {
            $in_field = (($in_field == null) ? "NULL" : "'".mysql_real_escape_string($in_field, $this->link)."'");
        }
        $this->record_count++;
        $this->row_array[] = "(".implode(",", $in_row).")";
        if (count($this->row_array) > $this->rows_to_process)
        {
            $ret =  $this->process_rows();
        }
        return $ret;
    }
    function process_rows()
    {
        $ret = true;
        $sql = "INSERT INTO ".$this->table_name." ".$this->field_name_store." VALUES ".implode(",", $this->row_array)." ".$this->update_clause;
        if (!mysql_query($sql, $this->link))
        {
            $ret = false;
        }
        $this->row_array = array();
        return $ret;
    }
    public function set_rows_to_process($rows_to_process)
    {
        if (is_numeric($rows_to_process) and intval($rows_to_process) > 0)
        {
            $this->rows_to_process = $rows_to_process;
        }
    }
}

?>

然后您将使用如下内容: -

$ProcessMatches = new table_process($link, 'matches', ' ON DUPLICATE KEY UPDATE delta=VALUES(delta)', true);
$ProcessMatches->field_names(array('id', 'delta'));

$ProcessMatches ->make_row(array('id'=>$id1, 'delta'=>$delta1));
$ProcessMatches ->make_row(array('id'=>$id2, 'delta'=>$delta2));
$ProcessMatches ->make_row(array('id'=>$id3, 'delta'=>$delta3));
$ProcessMatches ->make_row(array('id'=>$id4, 'delta'=>$delta4));
$ProcessMatches ->make_row(array('id'=>$id5, 'delta'=>$delta5));
$ProcessMatches ->make_row(array('id'=>$id6, 'delta'=>$delta6));

unset($ProcessMatches);

该类采用连接链接和表名/列名以及更新子句(如果需要)。

您插入的每一行都是由类占用并为插入而构建的。一旦有255行准备好插入,它就会插入它们并擦除存储它们的数组。完成后,取消设置触发__DESTRUCT方法的对象,该方法执行最终插入。