默认情况下如何在MySql中对数据进行排序

时间:2013-03-11 19:22:45

标签: mysql

如果我在MySQL数据库中有1000行,我知道使用TOPLIMIT会使查询更快,但我想知道,默认情况下数据的排序方式是什么?

默认情况下如何设置order by timeusername,以便轻松快捷地使用TOPLIMIT

4 个答案:

答案 0 :(得分:4)

在InnoDB 中,行以主键顺序存储。如果您使用LIMIT而没有ORDER BY,则您将始终获得具有最低主键值的行,即使您以随机顺序插入它们也是如此。

create table foo (id int primary key, x char(1), y int) engine=InnoDB;
insert into foo values (5, 'A', 123);
insert into foo values (9, 'B', 234);
insert into foo values (2, 'C', 345);
insert into foo values (4, 'D', 456);
insert into foo values (1, 'E', 567);
select * from foo;
+----+------+------+
| id | x    | y    |
+----+------+------+
|  1 | E    |  567 |
|  2 | C    |  345 |
|  4 | D    |  456 |
|  5 | A    |  123 |
|  9 | B    |  234 |
+----+------+------+

在MyISAM 中,行存储在适合的任何位置。最初,这意味着行会附加到数据文件中,但是当您删除行并插入新行时,已删除行留下的间隙将被新行重用。

create table bar (id int primary key, x char(1), y int) engine=MyISAM;
insert into bar values (1, 'A', 123);
insert into bar values (2, 'B', 234);
insert into bar values (3, 'C', 345);
insert into bar values (4, 'D', 456);
insert into bar values (5, 'E', 567);
select * from bar;
+----+------+------+
| id | x    | y    |
+----+------+------+
|  1 | A    |  123 |
|  2 | B    |  234 |
|  3 | C    |  345 |
|  4 | D    |  456 |
|  5 | E    |  567 |
+----+------+------+
delete from bar where id between 3 and 4;
insert into bar values (6, 'F', 678);
insert into bar values (7, 'G', 789);
insert into bar values (8, 'H', 890);
select * from bar;
+----+------+------+
| id | x    | y    |
+----+------+------+
|  1 | A    |  123 |
|  2 | B    |  234 |
|  7 | G    |  789 | <-- new row fills gap
|  6 | F    |  678 | <-- new row fills gap
|  5 | E    |  567 |
|  8 | H    |  890 | <-- new row appends at end
+----+------+------+

如果您使用InnoDB,则另一种例外情况是,您是从辅助索引而不是从主索引检索行。当您在EXPLAIN输出中看到“使用索引”注释时会发生这种情况。

alter table foo add index (x);
select id, x from foo;
+----+------+
| id | x    |
+----+------+
|  5 | A    |
|  9 | B    |
|  2 | C    |
|  4 | D    |
|  1 | E    |
+----+------+

如果你有更复杂的连接查询,它会变得更加复杂,因为你将获得所访问的第一个表的默认顺序返回的行(其中“first”依赖于优化器选择表的顺序),然后连接表中的行将取决于上一个表中行的顺序。

select straight_join foo.*, bar.* from bar join foo on bar.x=foo.x;
+----+------+------+----+------+------+
| id | x    | y    | id | x    | y    |
+----+------+------+----+------+------+
|  1 | E    |  567 |  5 | E    |  567 |
|  5 | A    |  123 |  1 | A    |  123 |
|  9 | B    |  234 |  2 | B    |  234 |
+----+------+------+----+------+------+

select straight_join foo.*, bar.* from foo join bar on bar.x=foo.x;
+----+------+------+----+------+------+
| id | x    | y    | id | x    | y    |
+----+------+------+----+------+------+
|  5 | A    |  123 |  1 | A    |  123 |
|  9 | B    |  234 |  2 | B    |  234 |
|  1 | E    |  567 |  5 | E    |  567 |
+----+------+------+----+------+------+

最重要的是,最好是明确的:当您使用LIMIT时,请指定ORDER BY

答案 1 :(得分:2)

  

默认情况下如何按时间或用户名进行排序,以便使用TOP或LIMIT更容易,更快?

使用 InnoDB 作为引擎时,可以将一个索引(列或其中的集合)设置为主键。如果这些值是唯一的,则存储时将按此顺序排序。

如果将常规索引用作查询条件的一部分,或者查询从所有行获取数据,则可以使用常规索引使排序更快。如果您的标准使用除您正在排序的字段之外的其他索引,他们将无法提供帮助。

实施例

鉴于下表:

| username (Primary) | time (Index) | country |

这些查询将使用索引进行排序:

select * from users order by time #Will use the index

select * from users where time between X and Y order by time #Will also use the index

这不会(在大多数情况下......)使用索引进行排序:

select * from users where country = China order by time

答案 2 :(得分:0)

它通常以插入的顺序出现,但你不能依赖它。如果您需要特定订单,请始终指定。

将索引添加到“时间”和“用户名”以使​​其更快,并且只选择您需要的数据。

答案 3 :(得分:0)

“默认”订单未指定(即不可靠)

将一个ORDER BY子句添加到select中以确保。