我经常遇到我想确定某个值是否在表格中的情况。查询通常经常在短时间内发生,并且搜索的值相似,因此我希望以最有效的方式执行此操作。我现在拥有的是
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的。
答案 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或各种替代方案。