MySQL:哪些索引用于简单范围选择?

发布于 2024-09-18 22:50:13 字数 1447 浏览 6 评论 0原文

我有一个大约有 3000 万行的表(并且还在不断增长!),目前我在简单的范围选择方面遇到了一些问题。

查询看起来像这样:

SELECT SUM( CEIL( dlvSize / 100 ) ) as numItems
FROM log
WHERE timeLogged BETWEEN 1000000 AND 2000000
AND user = 'example'</pre>

需要几分钟才能完成,我认为解决方案将位于我正在使用的索引处。这是解释的结果:

+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+
| id | select_type | table | type  | possible_keys                   | key     | key_len | ref  | rows     | Extra       |
+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+
|  1 | SIMPLE      | log   | range | PRIMARY,timeLogged              | PRIMARY | 4       | NULL | 11839754 | Using where | 
+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+

我的表结构是这样的(减少以使其更好地解决问题):

CREATE TABLE IF NOT EXISTS `log` (
  `origDomain` varchar(64) NOT NULL default '0',
  `timeLogged` int(11) NOT NULL default '0',
  `orig` varchar(128) NOT NULL default '',
  `rcpt` varchar(128) NOT NULL default '',
  `dlvSize` varchar(255) default NULL,
  `user` varchar(255) default NULL,
  PRIMARY KEY  (`timeLogged`,`orig`,`rcpt`),
  KEY `timeLogged` (`timeLogged`),
  KEY `orig` (`orig`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

我可以做些什么来优化表上的这个查询或索引吗?

I have a table with ~30 million rows ( and growing! ) and currently i have some problems with a simple range select.

The query, looks like this one:

SELECT SUM( CEIL( dlvSize / 100 ) ) as numItems
FROM log
WHERE timeLogged BETWEEN 1000000 AND 2000000
AND user = 'example'</pre>

It takes minutes to finish and i think that the solution would be at the indexes that i'm using. Here is the result of explain:

+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+
| id | select_type | table | type  | possible_keys                   | key     | key_len | ref  | rows     | Extra       |
+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+
|  1 | SIMPLE      | log   | range | PRIMARY,timeLogged              | PRIMARY | 4       | NULL | 11839754 | Using where | 
+----+-------------+-------+-------+---------------------------------+---------+---------+------+----------+-------------+

My table structure is this one ( reduced to make it fit better on the problem ):

CREATE TABLE IF NOT EXISTS `log` (
  `origDomain` varchar(64) NOT NULL default '0',
  `timeLogged` int(11) NOT NULL default '0',
  `orig` varchar(128) NOT NULL default '',
  `rcpt` varchar(128) NOT NULL default '',
  `dlvSize` varchar(255) default NULL,
  `user` varchar(255) default NULL,
  PRIMARY KEY  (`timeLogged`,`orig`,`rcpt`),
  KEY `timeLogged` (`timeLogged`),
  KEY `orig` (`orig`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Any ideas of what can I do to optimize this query or indexes on my table?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

我一向站在原地 2024-09-25 22:50:13

您可能想尝试添加复合索引 on (user, timeLogged)

CREATE TABLE IF NOT EXISTS `log` (
  ...
  KEY `user_timeLogged` (user, timeLogged),
  ...
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

相关 Stack Overflow 帖子:

You may want to try adding a composite index on (user, timeLogged):

CREATE TABLE IF NOT EXISTS `log` (
  ...
  KEY `user_timeLogged` (user, timeLogged),
  ...
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Related Stack Overflow post:

你与清晨阳光 2024-09-25 22:50:13

除了其他答案提出的建议之外,我注意到表中有一列 user ,它是 varchar(255) 。如果它引用用户表中的列,则 1) 向该表添加整数 ID 列并将其用作主键和其他表中的引用列很可能会更有效; 2)您正在使用InnoDB,那么为什么不利用它提供的外键功能呢?

考虑一下,如果您按 varchar(n) 列建立索引,则它会被视为索引中的 char(n),因此当前主键的每一行都会占用索引中 4 + 128 + 128 = 260 字节。

In addition to the suggestions made by the other answers, I note that you have a column user in the table which is a varchar(255). If this refers to a column in a table of users, then 1) it would most likely to far more efficient to add an integer ID column to that table, and use that as the primary key and as a referencing column in other tables; 2) you are using InnoDB, so why not take advantage of the foreign key capabilities it offers?

Consider that if you index by a varchar(n) column, it is treated like a char(n) in the index, so each row of your current primary key takes up 4 + 128 + 128 = 260 bytes in the index.

心碎无痕… 2024-09-25 22:50:13

用户上添加索引。

Add an index on user.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文