确定值是否在表中的最有效方法

时间:2013-06-17 20:14:16

标签: php sql performance

我经常遇到我想确定某个值是否在表格中的情况。查询通常经常在短时间内发生,并且搜索的值相似,因此我希望以最有效的方式执行此操作。我现在拥有的是

if($statment = mysqli_prepare($link, 'SELECT name FROM inventory WHERE name = ? LIMIT 1'))//name and inventory are arbitrarily chosen for this example
{
    mysqli_stmt_bind_param($statement, 's', $_POST['check']);
    mysqli_stmt_execute($statement);
    mysqli_stmt_bind_result($statement, $result);
    mysqli_stmt_store_result($statement);//needed for mysqli_stmt_num_rows
    mysqli_stmt_fetch($statement);
}
if(mysqli_stmt_num_rows($statement) == 0)
        //value in table
else
        //value not in table

是否需要调用所有mysqli_stmt_*函数?正如this question中讨论的mysqli_stmt_num_rows()工作一样,必须从数据库服务器下载整个结果集。我担心这是浪费,需要太长时间,因为我知道有1行或0行。使用SQL count()函数而不是打扰mysqli_stmt_store_result()会更有效吗?还有其他想法吗?

我注意到prepared statement manual说“准备好的语句或参数化语句用于以高效率重复执行相同的语句”。什么是高效的,它是什么意思相同的声明?例如,如果两个单独的预备语句被评估为相同,那么它仍然会更有效吗?

顺便说一句,我使用MySQL但不想添加标签,因为解决方案可能不是特定于MySQL的。

3 个答案:

答案 0 :(得分:2)

if($statment = mysqli_prepare($link, 'SELECT name FROM inventory WHERE name = ? LIMIT      1'))//name and inventory are arbitrarily chosen for this example
{
    mysqli_stmt_bind_param($statement, 's', $_POST['check']);
    mysqli_stmt_execute($statement);
    mysqli_stmt_store_result($statement);
}
if(mysqli_stmt_num_rows($statement) == 0)
    //value not in table
else
    //value in table

我相信这就足够了。请注意,我切换//值不在表中 和//表中的值。

答案 1 :(得分:0)

这实际上取决于您要搜索的字段类型。确保您在该字段上有索引,并且该索引适合内存。如果是,SELECT COUNT(*) FROM <your_table> WHERE <cond_which_use_index> LIMIT 1。重要的部分是LIMIT 1,它可以防止不必要的查找。您可以运行EXPLAIN SELECT ...来查看使用的索引,可能会提示或禁止其中一些索引,这取决于您。 COUNT(*)快速运行,它很快就被设计返回结果优化(仅限MyISAM,对于InnoDB,由于ACID,整个东西有点不同)。 COUNT(*)SELECT <some_field(s)>之间的主要区别在于count不执行任何数据读取,而(*)它不关心某个字段是否为NULL,只是按最合适的索引计算行数(在内部选择)。实际上我可以建议,即使是InnoDB,它也是一种最快的技术。

也使用案例。如果您希望插入唯一值,请对该字段进行约束并使用INSERT IGNORE,如果您要删除可能不在表格DELETE IGNORE中的值,而UPDATE IGNORE也是如此。

查询分析器自己定义两个查询是否相同并管理查询缓存,您不必担心它。

准备和常规查询之间的区别在于第一个查询分别包含规则和数据,因此分析器可以定义哪些数据是动态的,更好地处理,优化等等。对于常规查询,它可以做同样的事情,但是为了准备我们说我们稍后会重用它并给出一个提示,哪些数据是可变的,哪些是固定的。我在MySQL内部的表现不是很好,所以你可以在更具体的网站上提出这样的问题来简单地理解细节。

P.S。:MySQL中的预处理语句是会话全局的,因此在会话之后,它们被定义为已被解除分配的末尾。确切的行为和可能的内部MySQL缓存是一个额外调查的主题。

答案 2 :(得分:-1)

这是内存缓存非常擅长的东西。像这样的东西应该比大多数微优化尝试(伪代码!)更好地工作:

function check_if_value_is_in_table($value) {
  if ($cache->contains_key($value)) {
    return $cache->get($value);
  }
  // run the SQL query here, put result in $result
  // note: I'd benchmark if using mysqli_prepare actually helps
  // performance-wise
  $cache->put($value, $result);
  return $result;
}

查看memcache或各种替代方案。