是否可以指定 MySQL 索引的排序顺序?
Is it possible to specify sorting order to MySQL index?
我有一个 items
table 和 category_id
字段。
有一个特定的规则可以按 category_id
对项目进行排序。
我通常这样排序数据:
SELECT * FROM items ORDER BY FIELD(category_id, 2, 5, 1, 4, 3)
-- In this example, the "rule" is sorting in order of (2, 5, 1, 4, 3)
在这种情况下,简单地在 category_id
字段上创建索引并不能加快排序项目的速度,因为索引对 category_id 进行排序就像 (1, 2, 3, 4) , 5).
在category_id字段上CREATE INDEX
时是否可以指定排序规则?
(然后简单地 SELECT * FROM items ORDER BY category_id
工作)
或者我是否必须创建另一个字段,如 sorted_category_id
,并根据顺序规则排序?
正如 Akina 所说,我可以使用生成的列。
https://dev.mysql.com/doc/refman/8.0/en/create-index.html
将列添加到 items
table,并为其添加索引,确实是一种注重速度的解决方案。通过将其设为 generated 列,您可以确保一致性,通过将其设为 virtual 列,您可以将额外数据移动到索引中(如果你创造它)。所以像这样进行:
ALTER TABLE items ADD (
category_ord int GENERATED ALWAYS AS (FIELD(category_id, 2, 5, 1, 4, 3)) VIRTUAL
);
CREATE INDEX idx_items_category_ord ON items(category_ord);
SELECT * FROM items ORDER BY category_ord;
备选
或者,规范化 方法是向 category
table 添加一列。如果您有很多类别,这将对性能产生轻微影响,但不会造成一致性问题,并节省 space。要实现该想法,请按以下步骤操作:
如果您没有 category
table,请创建它:
CREATE TABLE category(
id int NOT NULL PRIMARY KEY,
ord int NOT NULL,
name varchar(100)
);
根据需要填充 ord
字段(或您想要的任何名称):
INSERT INTO category(id, ord, name) VALUES
(1, 30, 'cat1'),
(2, 10, 'cat2'),
(3, 50, 'cat3'),
(4, 40, 'cat4'),
(5, 20, 'cat5');
并在 ord
列上添加索引:
CREATE INDEX category_ord ON category(ord);
现在查询将是:
SELECT *
FROM items
INNER JOIN category
ON items.category_id = category.id
ORDER BY category.ord;
数据库引擎现在可以决定使用(或不使用)ord
列上的索引,这取决于它自己的分析。如果想强制使用,可以使用FORCE INDEX
:
SELECT *
FROM items
INNER JOIN category FORCE INDEX category(category_ord)
ON items.category_id = category.id
ORDER BY category.ord;
请注意,引擎也可以在 items.category_id
上使用您的索引,以按值查找。
我有一个 items
table 和 category_id
字段。
有一个特定的规则可以按 category_id
对项目进行排序。
我通常这样排序数据:
SELECT * FROM items ORDER BY FIELD(category_id, 2, 5, 1, 4, 3)
-- In this example, the "rule" is sorting in order of (2, 5, 1, 4, 3)
在这种情况下,简单地在 category_id
字段上创建索引并不能加快排序项目的速度,因为索引对 category_id 进行排序就像 (1, 2, 3, 4) , 5).
在category_id字段上CREATE INDEX
时是否可以指定排序规则?
(然后简单地 SELECT * FROM items ORDER BY category_id
工作)
或者我是否必须创建另一个字段,如 sorted_category_id
,并根据顺序规则排序?
正如 Akina 所说,我可以使用生成的列。 https://dev.mysql.com/doc/refman/8.0/en/create-index.html
将列添加到 items
table,并为其添加索引,确实是一种注重速度的解决方案。通过将其设为 generated 列,您可以确保一致性,通过将其设为 virtual 列,您可以将额外数据移动到索引中(如果你创造它)。所以像这样进行:
ALTER TABLE items ADD (
category_ord int GENERATED ALWAYS AS (FIELD(category_id, 2, 5, 1, 4, 3)) VIRTUAL
);
CREATE INDEX idx_items_category_ord ON items(category_ord);
SELECT * FROM items ORDER BY category_ord;
备选
或者,规范化 方法是向 category
table 添加一列。如果您有很多类别,这将对性能产生轻微影响,但不会造成一致性问题,并节省 space。要实现该想法,请按以下步骤操作:
如果您没有 category
table,请创建它:
CREATE TABLE category(
id int NOT NULL PRIMARY KEY,
ord int NOT NULL,
name varchar(100)
);
根据需要填充 ord
字段(或您想要的任何名称):
INSERT INTO category(id, ord, name) VALUES
(1, 30, 'cat1'),
(2, 10, 'cat2'),
(3, 50, 'cat3'),
(4, 40, 'cat4'),
(5, 20, 'cat5');
并在 ord
列上添加索引:
CREATE INDEX category_ord ON category(ord);
现在查询将是:
SELECT *
FROM items
INNER JOIN category
ON items.category_id = category.id
ORDER BY category.ord;
数据库引擎现在可以决定使用(或不使用)ord
列上的索引,这取决于它自己的分析。如果想强制使用,可以使用FORCE INDEX
:
SELECT *
FROM items
INNER JOIN category FORCE INDEX category(category_ord)
ON items.category_id = category.id
ORDER BY category.ord;
请注意,引擎也可以在 items.category_id
上使用您的索引,以按值查找。