具有数百万行的DB的有效索引

时间:2012-05-22 16:06:57

标签: mysql database-design indexing

我有一个MYISAM MySQL数据库表,里面有数百万行,我被要求使用它,但我需要先加快查询速度。

之前根本没有索引!我在'type'列上添加了一个新的索引,但是我想知道是否还有其他列可能是最好的索引?

这是我的CREATE TABLE:

CREATE TABLE `clicks` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`companyid` int(11) DEFAULT '0',
`type` varchar(32) NOT NULL DEFAULT '',
`contextid` int(11) NOT NULL DEFAULT '0',
`period` varchar(16) NOT NULL DEFAULT '',
`timestamp` int(11) NOT NULL DEFAULT '0',
`location` varchar(32) NOT NULL DEFAULT '',
`ip` varchar(32) DEFAULT NULL,
`useragent` varchar(64) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `companyid` (`companyid`,`type`,`period`),
KEY `type` (`type`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

典型的SELECT语句通常会按companyidtypecontextid列进行过滤。

例如:

SELECT period, count(period) as count FROM clicks WHERE contextid in (123) AND timestamp > 123123123 GROUP BY period ORDER BY timestamp ASC

SELECT period, count(period) as count FROM clicks WHERE contextid in (123) AND type IN('direct') AND timestamp > 123123123 GROUP BY period ORDER BY timestamp ASC

我的问题的最后一部分是这样的:当我在type上添加索引时花了大约1小时 - 如果我要添加或删除多个索引,你可以在一个查询中执行它还是你有一个接一个地做它们并等待每个完成?

感谢您的想法。

5 个答案:

答案 0 :(得分:3)

索引真的很强大,但并不像你想象的那么多黑色艺术。了解MySQL的EXPLAIN PLAN功能,这将帮助您系统地找到可以进行改进的地方:

http://dev.mysql.com/doc/refman/5.5/en/execution-plan-information.html

答案 1 :(得分:1)

要添加的索引实际上取决于您的查询。您正在排序(GROUP BY)或选择(WHERE)的任何内容都是索引的良好候选者。

您可能还想查看how Mysql uses indexes

关于添加索引所花费的时间,您确定要添加多个索引,可以执行mysqldump,手动编辑.sql文件中的表结构,然后重新导入。这可能需要一段时间,但至少您可以立即执行所有更改。但是,这并不适合你去测试的想法......所以要谨慎使用这种方法。 (我在修改了一些具有相同结构的表时想要为所有表添加一些索引。)

另外,我不是100%肯定,但我认为当你添加一个索引时,Mysql会用索引创建一个表的副本,然后删除原始表 - 所以要确保你的空间足够服务器/分区用于表格的当前大小&一些保证金。

答案 2 :(得分:0)

我认为timestampperiod可以在WHERE子句中使用时编入索引。

使用contextid in (123)而不是contextid = 123代替type IN('direct')使用type = 'direct'

答案 3 :(得分:0)

这是您的一个查询,分为多行,因此更容易阅读。

SELECT period, count(period) as count 
FROM clicks 
WHERE contextid in (123) 
AND timestamp > 123123123 
GROUP BY period 
ORDER BY timestamp ASC

我甚至不确定这是一个有效的查询。我认为你的GROUP BY和ORDER BY必须在SQL中匹配。我认为您必须在count订购,因为GROUP BY会在period订购。

优化查询的重要部分是WHERE子句。在这种情况下,contextidtimestamp上的索引会加快查询速度。

显然,您无法索引每个WHERE子句。您索引最常见的WHERE子句。

我会一次一个地向现有表添加索引。是的,它很慢。但是你应该只需要添加一次索引。

答案 4 :(得分:0)

您可以在单个查询中添加多个索引。这将节省一些时间,但在等待整个查询完成时,表将无法访问:

ALTER TABLE table1 ADD INDEX `Index1`('col1'),
 ADD INDEX `Index2`('col2')

关于indexes,这是一个复杂的主题。但是,在WHERE子句中包含的具有高基数的单列上添加索引是一个很好的起点。 MySQL将尝试为查询选择最佳索引并使用它。

要进一步调整效果,您应该考虑multi-column indexes,我认为您已经使用'companyid'索引实现了。{/ p>

能够在GROUP BYORDER BY子句中使用索引依赖于很多条件,您可能需要阅读这些条件。

为了最好地利用索引,数据库服务器必须有足够的RAM来将索引完全存储在内存中,并且必须正确配置服务器才能实际利用内存。