0

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

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_*函数?正如在这个问题中所讨论的那样mysqli_stmt_num_rows(),整个结果集必须从数据库服务器下载。我担心这是一种浪费并且需要很长时间,因为我知道有 1 或 0 行。count()使用 SQL函数而不用担心会更有效mysqli_stmt_store_result()吗?还有其他想法吗?

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

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

4

3 回答 3

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

我相信这就足够了。请注意,我切换了 //value not in table 和 //value in table。

于 2013-06-17T20:34:42.280 回答
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 内部不是很好,所以你可以在更具体的网站上问这样的问题,以简而言之了解细节。

PS:MySQL 中的准备好的语句是会话全局的,因此在会话结束后它们被定义,它们被释放。确切的行为和可能的内部 MySQL 缓存是额外调查的主题。

于 2013-06-17T21:18:05.947 回答
-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或各种替代方案。

于 2013-06-17T20:43:56.747 回答