多列索引和SQL查询的顺序

发布于 2024-10-15 13:03:25 字数 398 浏览 0 评论 0原文

关于MySQL中多列索引的顺序,我发现了两个相反的说法。 这篇文章这里有在注释中,(a, b) 索引也可用于 (b = value1 AND a = value2) 的查询。此常见问题解答条目 这里说(在底部)完全相反(不会使用索引)。什么是正确的? PostgreSQL 怎么样?它的行为方式相同吗?

I found two contrary statements regarding the order of multi column indexes in MySQL.
This post here has in the comments that an (a, b) index would also be used for a query with (b = value1 AND a = value2). This FAQ entry here says (on the bottom) exactly the opposite (index won't be used). What is correct? And how about PostgreSQL? Does it behave the same way?

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

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

发布评论

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

评论(1

温柔一刀 2024-10-22 13:03:25

首先我要说的是,没有灵丹妙药的答案。

(a,b) 复合索引上的索引将用于满足查询(b=value1 和 a=value2)。请注意,WHERE 子句中“b”出现在“a”之前并不重要,因为查询引擎知道您正在处理 a 和 b。如果选择性不够高,它仍然可能无法使用。

话虽如此,

2. [SELECT * FROM buyers WHERE last_name=? AND first_name=? AND zip=?]
can't use the index.

这必须是我今天令人难以置信的常见问题解答条目中发现的最重要的。它部分正确,只是因为 SELECT * 需要查找回表,因此复合索引的任何好处都会减半(或进一步最小化)。比较此代码末尾的两个查询,而不是

CREATE TABLE buyers(
 buyer_id INT NOT NULL AUTO_INCREMENT,
 first_name CHAR(19) NOT NULL,
 last_name CHAR(19) NOT NULL,
 zip CHAR(5) NOT NULL,
 state_code CHAR(2) NOT NULL,
 PRIMARY KEY (buyer_id)
 );

insert buyers values
(991,'zeshan ','Nadeem ',92082,'CA'),
(992,'Ken ','Marcus ',92082,'CA'),
(993,'Tariq ','Iqbal ',92082,'CA'),
(994,'Tariq ','Iqbal ',92082,'CA'),
(995,'Hasnat ','Ahmad ',92083,'NY'),
(996,'Tariq ','Iqbal ',92082,'DC'),
(997,'Keith ','Worlf ',93083,'NG'),
(998,'Ashley ','Lewis ',92088,'NJ'),
(999,'Tariq ','Mehmood ',99088,'TX');

ALTER TABLE buyers ADD INDEX idx_firstname (first_name);
ALTER TABLE buyers ADD INDEX idx_last_name (last_name);
ALTER TABLE buyers ADD INDEX idx_zip (zip);
ALTER TABLE buyers ADD INDEX idx_flname_zip(first_name,last_name,zip);

在单独的查询中运行此查询

explain
SELECT first_name,last_name,zip FROM buyers WHERE first_name='Tariq' AND last_name='Iqbal' AND zip=92082;

,然后

explain
SELECT last_name,first_name,zip FROM buyers WHERE last_name='Iqbal' AND first_name='Tariq' AND zip=92082;

它们将显示相同的计划

First let me say, there is no silver bullet answer.

And index on (a,b) composite index will be used to satisfy a query (b=value1 and a=value2). Note that it does not matter that "b" is presented before "a" in the WHERE clause, since the query engine knows you are dealing with both a and b. It STILL may not be used if the selectivity is not high enough.

Having said that

2. [SELECT * FROM buyers WHERE last_name=? AND first_name=? AND zip=?]
can't use the index.

That has to top my unbelievable-faq-entry find for today. It is partially right, and only because the SELECT * requires a lookup back to the table so any benefit from the composite index is halved (or further minimized). Compare the two queries at the end of this code instead

CREATE TABLE buyers(
 buyer_id INT NOT NULL AUTO_INCREMENT,
 first_name CHAR(19) NOT NULL,
 last_name CHAR(19) NOT NULL,
 zip CHAR(5) NOT NULL,
 state_code CHAR(2) NOT NULL,
 PRIMARY KEY (buyer_id)
 );

insert buyers values
(991,'zeshan ','Nadeem ',92082,'CA'),
(992,'Ken ','Marcus ',92082,'CA'),
(993,'Tariq ','Iqbal ',92082,'CA'),
(994,'Tariq ','Iqbal ',92082,'CA'),
(995,'Hasnat ','Ahmad ',92083,'NY'),
(996,'Tariq ','Iqbal ',92082,'DC'),
(997,'Keith ','Worlf ',93083,'NG'),
(998,'Ashley ','Lewis ',92088,'NJ'),
(999,'Tariq ','Mehmood ',99088,'TX');

ALTER TABLE buyers ADD INDEX idx_firstname (first_name);
ALTER TABLE buyers ADD INDEX idx_last_name (last_name);
ALTER TABLE buyers ADD INDEX idx_zip (zip);
ALTER TABLE buyers ADD INDEX idx_flname_zip(first_name,last_name,zip);

Run this in a separate query

explain
SELECT first_name,last_name,zip FROM buyers WHERE first_name='Tariq' AND last_name='Iqbal' AND zip=92082;

And then this

explain
SELECT last_name,first_name,zip FROM buyers WHERE last_name='Iqbal' AND first_name='Tariq' AND zip=92082;

They will show the same plan

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