>我正在对包含数千行的表运行查询:
$sql="select * from call_history where extension_number = '0536*002' and flow = 'in' and DATE(initiated) = '".date("Y-m-d")."' ";
并且需要很长时间才能返回结果。
SQL本身是
select *
from call_history
where extension_number = '0536*002'
and flow = 'in'
and DATE(initiated) = 'dateFromYourPHPcode'
有没有办法让它运行得更快? 我应该把 where DATE(initiated) = '".date("Y-m-d")."'
放在 extension_number
where 子句之前吗?
还是我应该选择DATE(initiated) = '".date("Y-m-d")."'
的所有行并将其放入 while 循环中,然后运行所有其他查询(where extension_number = ...)
while 循环?
以下是一些建议:
1(将SELECT *
替换为所需的唯一字段。
2( 在要作为输出的表字段上添加索引。
3( 避免在循环中运行查询。这会导致对 SQL 服务器发出多个请求。
4(一次获取所有数据。
5( 根据需要应用LIMIT
标签。不要选择所有记录。
6( 触发两个不同的查询:一个用于计算记录总数,另一个用于获取每页的记录数(例如 10、20、50 等(
7( 如果适用,请创建数据库视图并从中获取数据而不是表。谢谢
WHERE
下子句的顺序与优化无关。
专业提示,也是其他人建议的:永远不要在程序的查询中使用SELECT *
除非您有充分的理由这样做。"我不想写出我需要的列的名称"不是一个很好的理由。始终枚举所需的列。 当您需要的数据列列表可用时,MySQL 和其他数据库系统通常可以以令人惊讶的方式优化事物。
您的查询包含此选择条件。
AND DATE(initiated) = 'dateFromYourPHPcode'
请注意,此搜索条件采用以下形式
FUNCTION(column) = value
这种形式的搜索会挫败对该列使用任何索引。initiated
列具有TIMESTAMP
数据类型。 试试这个:
AND initiated >= 'dateFromYourPHPcode'
AND initiated < 'dateFromYourPHPcode' + INTERVAL 1 DAY
这将找到特定日期的所有initiated
项目。而且,由于它不使用列值的函数,因此可以使用索引范围扫描来执行此操作,这表现良好。 如果没有索引,它可能会或可能不会提供帮助。值得一试。
我怀疑您对此特定搜索的理想索引将由以下人员创建
ALTER TABLE call_history
ADD INDEX flowExtInit (flow, extension_number, initiated)
如果您的查询需要良好的性能,则应要求数据库管理员添加此索引。
您应该将索引添加到表中。这样MySql将获取得更快。我还没有测试过,但命令应该是这样的:
ALTER TABLE `call_history ` ADD INDEX `callhistory` (`extension_number`,`flow`,`extension_number`,`DATE(initiated)`);