如何以正确的方式索引查询

时间:2013-02-09 11:21:46

标签: php mysql optimization indexing

我正在尝试让我的数据库更加优化,并且正在开始索引它,但不确定如何正确执行。

我有这个问题:

$year = date("Y");
$thisYear = $year;
//$nextYear = $thisYear + 1; 
$sql = mysql_query("SELECT SUM(points) as userpoints
                                          FROM ".$prefix."_publicpoints
                                          WHERE date BETWEEN '$thisYear" . "-01-01' AND '$thisYear" . "-12-31' AND fk_player_id = $playerid");
$row = mysql_fetch_assoc($sql); 
$userPoints = $row['userpoints'];

$sql = mysql_query("SELECT 
                       fk_player_id
                    FROM ".$prefix."_publicpoints
                    WHERE date BETWEEN '$thisYear" . "-01-01' AND '$thisYear" . "-12-31'
                    GROUP BY fk_player_id
                    HAVING SUM(points) > $userPoints");
$row = mysql_fetch_assoc($sql);
$userWrank = mysql_num_rows($sql)+1;

我不确定如何索引这个?我已经尝试索引fk_player_id,但它仍然可以查看所有行(287937)。

我已将日期字段编入索引,并在EXPLAIN中将其返回给我:

1 简单 nf_publicpoints 范围 IDXdate IDXdate 3 空值 143969 使用推动条件的地方;使用临时......

我也有2次拨打同一张桌子...可以在一张桌子上完成吗?

如何对此进行索引和/或更聪明地完成?

3 个答案:

答案 0 :(得分:1)

你肯定应该花一些时间阅读索引,有很多关于它的文章,并且了解正在发生的事情很重要。

从广义上讲,索引会对表的行强制排序。

为简单起见,想象一个表只是一个大的CSV文件。每当插入一行时,它就会插入到最后。因此,表的“自然”排序只是插入行的顺序。

想象一下,您已经在一个非常基本的电子表格应用程序中加载了该CSV文件。所有这些电子表格都显示数据,并按顺序对行进行编号。

现在假设您需要在第三列中找到所有具有某些值“M”的行。鉴于您的可用性,您只有一个选项。您扫描表格,检查每行的第三列的值。如果你有很多行,这种方法(“表扫描”)可能需要很长时间!

现在想象一下,除了这个表,你还有一个索引。此特定索引是第三列中的值的索引。索引以一些有意义的顺序(例如,按字母顺序)列出第三列中的所有值,并且对于每个值,它提供了该值出现的行号列表。

现在您有一个很好的策略来查找第三列的值为M的所有行!例如,您可以执行二进制搜索!虽然表扫描要求您查看N行(其中N是行数),但二进制搜索仅要求您查看log-n索引条目,在最坏的情况下。哇,这肯定容易多了!

当然,如果你有这个索引,并且你正在向表中添加行(最后,因为这是我们的概念表的工作原理),你需要每次都更新索引。因此,当您编写新行时,您会做更多的工作,但是当您搜索某些内容时,可以节省大量时间。

因此,通常,索引会在读取效率和写入效率之间进行权衡。没有索引,插入可以非常快 - 数据库引擎只是向表中添加一行。在添加索引时,引擎必须在执行插入时更新每个索引。

另一方面,阅读变得更快。

希望这涵盖了你的前两个问题(正如其他人已经回答的那样 - 你需要找到合适的平衡点)。

你的第三个场景有点复杂。如果您使用LIKE,索引引擎通常会帮助您将读取速度提升到第一个“%”。换句话说,如果您正在选择WHERE列LIKE'foo%bar%',数据库将使用索引查找列以“foo”开头的所有行,然后需要扫描该中间行集以查找子集包含“bar”。 SELECT ... WHERE列LIKE'%bar%'无法使用索引。我希望你能明白为什么。

最后,您需要开始考虑多个列上的索引。概念是相同的,并且行为类似于LIKE的东西 - 实际上,如果你有(a,b,c)的索引,引擎将继续尽可能从左到右使用索引。因此,对列a的搜索可能会使用(a,b,c)索引,就像(a,b)上的索引一样。但是,如果您搜索的是WHERE b = 5且c = 1,则引擎需要进行全表扫描。

希望这有助于提供一些亮点,但我必须重申,你最好花几个小时来寻找能够深入解释这些事情的好文章。阅读特定数据库服务器的文档也是一个好主意。查询规划者实现和使用索引的方式可以有很大的不同。

更多信息和示例请访问:http://blog.sqlauthority.com/category/sql-index/

答案 1 :(得分:0)

在日期列上尝试创建索引,索引fk_payer_id对此查询没有帮助。如果不起作用 - 粘贴说明......

有关Mysql中索引的更多信息,请查看此处:http://hackmysql.com/case1

答案 2 :(得分:0)

为什么不对日期列进行索引,看看这是如何在查找中评估的主要标准?