Covering index used despite missing columnInnoDB - Use combined index with primary key on GROUP BYMust an index cover all selected columns for it to be used for ORDER BY?Proper Index for WHERE X <> 1 AND Y <> 1 ORDER BY ZIs index on foreign key used? (No difference in EXPLAIN.)Awful execution plans after migrating from MySQL 5.5.11 to MariaDB 5.5.41MySQL query WHERE IN + ORDER BY, which EXPLAIN is better and how to avoid filesort?MySQL Query causing high CPU and taking forever to executeWhy is a query with a join and limit clause running so slow, even using a covering index?Do we need index on “order by” if the “where” clause alreday have index ( small data set )Primary index is being used, not the one which is on the field present in the where condition
Subtract the Folded Matrix
What is the most suitable position for a bishop here?
Non-misogynistic way to say “asshole”?
Why is it easier to balance a non-moving bike standing up than sitting down?
Print one file per line using echo
Extending prime numbers digit by digit while retaining primality
Warnings using NDSolve on wave PDE. "Using maximum number of grid points" , "Warning: scaled local spatial error estimate"
Should the party get XP for a monster they never attacked?
A word for delight at someone else's failure?
What happened to Hopper's girlfriend in season one?
Dates on degrees don’t make sense – will people care?
What are Elsa's reasons for selecting the Holy Grail on behalf of Donovan?
Is the continuity test limit resistance of a multimeter standard?
What are the current battlegrounds for people’s “rights” in the UK?
"Correct me if I'm wrong"
Why does independence imply zero correlation?
Prisoner on alien planet escapes by making up a story about ghost companions and wins the war
Definition of 'vrit'
Is there any proof that high saturation and contrast makes a picture more appealing in social media?
King or Queen-Which piece is which?
Cut the gold chain
Covering index used despite missing column
Why don't countries like Japan just print more money?
Methodology: Writing unit tests for another developer
Covering index used despite missing column
InnoDB - Use combined index with primary key on GROUP BYMust an index cover all selected columns for it to be used for ORDER BY?Proper Index for WHERE X <> 1 AND Y <> 1 ORDER BY ZIs index on foreign key used? (No difference in EXPLAIN.)Awful execution plans after migrating from MySQL 5.5.11 to MariaDB 5.5.41MySQL query WHERE IN + ORDER BY, which EXPLAIN is better and how to avoid filesort?MySQL Query causing high CPU and taking forever to executeWhy is a query with a join and limit clause running so slow, even using a covering index?Do we need index on “order by” if the “where” clause alreday have index ( small data set )Primary index is being used, not the one which is on the field present in the where condition
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I have the following query, using MariaDB 10 / InnoDB:
SELECT id, sender_id, receiver_id, thread_id, date_created, content
FROM user_message
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
This query fetches messages according to the given conditions and sorts by date created.
I have a covering index over (thread_id, date_created)
.
When running EXPLAIN, the correct index is used and I get the output "Using where", although the query is using a column in the middle of the statement that is not in the index. I can use any value for "placeholder = x" and the result is the same.
If I change the sorting to use another column, the EXPLAIN correctly indicates "Using where. Using filesort."
I'm having a head-scratching moment. Could anyone please shed light on this? What I would expect to see is that an additional filesort would be needed as the covering index could not be completed used due to the additional column.
index innodb mariadb covering-index
add a comment |
I have the following query, using MariaDB 10 / InnoDB:
SELECT id, sender_id, receiver_id, thread_id, date_created, content
FROM user_message
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
This query fetches messages according to the given conditions and sorts by date created.
I have a covering index over (thread_id, date_created)
.
When running EXPLAIN, the correct index is used and I get the output "Using where", although the query is using a column in the middle of the statement that is not in the index. I can use any value for "placeholder = x" and the result is the same.
If I change the sorting to use another column, the EXPLAIN correctly indicates "Using where. Using filesort."
I'm having a head-scratching moment. Could anyone please shed light on this? What I would expect to see is that an additional filesort would be needed as the covering index could not be completed used due to the additional column.
index innodb mariadb covering-index
add a comment |
I have the following query, using MariaDB 10 / InnoDB:
SELECT id, sender_id, receiver_id, thread_id, date_created, content
FROM user_message
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
This query fetches messages according to the given conditions and sorts by date created.
I have a covering index over (thread_id, date_created)
.
When running EXPLAIN, the correct index is used and I get the output "Using where", although the query is using a column in the middle of the statement that is not in the index. I can use any value for "placeholder = x" and the result is the same.
If I change the sorting to use another column, the EXPLAIN correctly indicates "Using where. Using filesort."
I'm having a head-scratching moment. Could anyone please shed light on this? What I would expect to see is that an additional filesort would be needed as the covering index could not be completed used due to the additional column.
index innodb mariadb covering-index
I have the following query, using MariaDB 10 / InnoDB:
SELECT id, sender_id, receiver_id, thread_id, date_created, content
FROM user_message
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
This query fetches messages according to the given conditions and sorts by date created.
I have a covering index over (thread_id, date_created)
.
When running EXPLAIN, the correct index is used and I get the output "Using where", although the query is using a column in the middle of the statement that is not in the index. I can use any value for "placeholder = x" and the result is the same.
If I change the sorting to use another column, the EXPLAIN correctly indicates "Using where. Using filesort."
I'm having a head-scratching moment. Could anyone please shed light on this? What I would expect to see is that an additional filesort would be needed as the covering index could not be completed used due to the additional column.
index innodb mariadb covering-index
index innodb mariadb covering-index
asked 8 hours ago
TomTom
1204
1204
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Case A
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY some_column DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
Using filesort
No problem there, right? If the index is used (to partially match the WHERE
condition), we still need a sort operation to order the results by some_column
(which is not in the index). We also need an extra check (Using Where) to keep only the rows that match the 2nd condition, too. OK.
Case B (the question)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
-- no "Using filesort"
So, why does it not need a sort here? Because the index is enough to sort as the query wants. There is of course the additional problem of the extra condition (AND placeholder = FALSE
) which is not covered by the index.
OK but we don't really need a sort here. The index can provide us with results that match the first condition (WHERE thread_id = 12345
) and are in the wanted order for output. The only additional check we need - and what the plan does - is to get the rows from the table, in the order provided by the index, and check this 2nd condition until we get 20 matches. That's what the **Using Where"" means.
We may get the 20 matches in the first 20 rows (so really good and fast) or in the first 100 (still likely fast enough) or in the first 1000000 (probably very, very slow) or we may get just 19 matches from the table even after reading all the matching rows from the index (really very slow on a big table). It all depends on the distribution of data.
Case C (even better plan)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(placeholder, thread_id, date_created)
Plan:
Index is used
-- no "Using Where"
-- no "Using filesort"
Now our index matches both conditions and the order by. The plan is pretty simple: get the first* 20 matches from the index and read the corresponding rows from the table. No extra check (No "Using Where") and no sort (no "Using filesort") needed.
first*: the first 20 when reading the index backwards from the end (as we have ORDER BY .. DESC
) but that's not a problem. B-tree indexes can be read forwards and backwards with almost equal performance.
Thank you - this is a great explanation.
– Tom
7 hours ago
add a comment |
Using index indicates a "Covering index" -- All the columns anywhere in theSELECT
are anywhere in the one index. So, you do not have a "covering" index. And it is not practical to make a covering index for your query (too many columns mentioned).
Using where -- mostly noise.
Using filesort -- The query needs a sort, but it might be in RAM or in a temp table. And there may be multiple sorts (eg,GROUP BY x ORDER BY b
)Either of these will make it possible to look only at 20 rows; any other index will require more rows be touched, possibly the entire table:
INDEX(thread_id, placeholder, date_created)
INDEX(placeholder, thread_id, date_created)No, the cardinality of the components of a composite index does not matter when ordering the columns in the index.
My Cookbook explains how to derive the optimal index, given a SELECT
.
add a comment |
Your Answer
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "182"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f240742%2fcovering-index-used-despite-missing-column%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Case A
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY some_column DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
Using filesort
No problem there, right? If the index is used (to partially match the WHERE
condition), we still need a sort operation to order the results by some_column
(which is not in the index). We also need an extra check (Using Where) to keep only the rows that match the 2nd condition, too. OK.
Case B (the question)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
-- no "Using filesort"
So, why does it not need a sort here? Because the index is enough to sort as the query wants. There is of course the additional problem of the extra condition (AND placeholder = FALSE
) which is not covered by the index.
OK but we don't really need a sort here. The index can provide us with results that match the first condition (WHERE thread_id = 12345
) and are in the wanted order for output. The only additional check we need - and what the plan does - is to get the rows from the table, in the order provided by the index, and check this 2nd condition until we get 20 matches. That's what the **Using Where"" means.
We may get the 20 matches in the first 20 rows (so really good and fast) or in the first 100 (still likely fast enough) or in the first 1000000 (probably very, very slow) or we may get just 19 matches from the table even after reading all the matching rows from the index (really very slow on a big table). It all depends on the distribution of data.
Case C (even better plan)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(placeholder, thread_id, date_created)
Plan:
Index is used
-- no "Using Where"
-- no "Using filesort"
Now our index matches both conditions and the order by. The plan is pretty simple: get the first* 20 matches from the index and read the corresponding rows from the table. No extra check (No "Using Where") and no sort (no "Using filesort") needed.
first*: the first 20 when reading the index backwards from the end (as we have ORDER BY .. DESC
) but that's not a problem. B-tree indexes can be read forwards and backwards with almost equal performance.
Thank you - this is a great explanation.
– Tom
7 hours ago
add a comment |
Case A
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY some_column DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
Using filesort
No problem there, right? If the index is used (to partially match the WHERE
condition), we still need a sort operation to order the results by some_column
(which is not in the index). We also need an extra check (Using Where) to keep only the rows that match the 2nd condition, too. OK.
Case B (the question)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
-- no "Using filesort"
So, why does it not need a sort here? Because the index is enough to sort as the query wants. There is of course the additional problem of the extra condition (AND placeholder = FALSE
) which is not covered by the index.
OK but we don't really need a sort here. The index can provide us with results that match the first condition (WHERE thread_id = 12345
) and are in the wanted order for output. The only additional check we need - and what the plan does - is to get the rows from the table, in the order provided by the index, and check this 2nd condition until we get 20 matches. That's what the **Using Where"" means.
We may get the 20 matches in the first 20 rows (so really good and fast) or in the first 100 (still likely fast enough) or in the first 1000000 (probably very, very slow) or we may get just 19 matches from the table even after reading all the matching rows from the index (really very slow on a big table). It all depends on the distribution of data.
Case C (even better plan)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(placeholder, thread_id, date_created)
Plan:
Index is used
-- no "Using Where"
-- no "Using filesort"
Now our index matches both conditions and the order by. The plan is pretty simple: get the first* 20 matches from the index and read the corresponding rows from the table. No extra check (No "Using Where") and no sort (no "Using filesort") needed.
first*: the first 20 when reading the index backwards from the end (as we have ORDER BY .. DESC
) but that's not a problem. B-tree indexes can be read forwards and backwards with almost equal performance.
Thank you - this is a great explanation.
– Tom
7 hours ago
add a comment |
Case A
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY some_column DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
Using filesort
No problem there, right? If the index is used (to partially match the WHERE
condition), we still need a sort operation to order the results by some_column
(which is not in the index). We also need an extra check (Using Where) to keep only the rows that match the 2nd condition, too. OK.
Case B (the question)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
-- no "Using filesort"
So, why does it not need a sort here? Because the index is enough to sort as the query wants. There is of course the additional problem of the extra condition (AND placeholder = FALSE
) which is not covered by the index.
OK but we don't really need a sort here. The index can provide us with results that match the first condition (WHERE thread_id = 12345
) and are in the wanted order for output. The only additional check we need - and what the plan does - is to get the rows from the table, in the order provided by the index, and check this 2nd condition until we get 20 matches. That's what the **Using Where"" means.
We may get the 20 matches in the first 20 rows (so really good and fast) or in the first 100 (still likely fast enough) or in the first 1000000 (probably very, very slow) or we may get just 19 matches from the table even after reading all the matching rows from the index (really very slow on a big table). It all depends on the distribution of data.
Case C (even better plan)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(placeholder, thread_id, date_created)
Plan:
Index is used
-- no "Using Where"
-- no "Using filesort"
Now our index matches both conditions and the order by. The plan is pretty simple: get the first* 20 matches from the index and read the corresponding rows from the table. No extra check (No "Using Where") and no sort (no "Using filesort") needed.
first*: the first 20 when reading the index backwards from the end (as we have ORDER BY .. DESC
) but that's not a problem. B-tree indexes can be read forwards and backwards with almost equal performance.
Case A
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY some_column DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
Using filesort
No problem there, right? If the index is used (to partially match the WHERE
condition), we still need a sort operation to order the results by some_column
(which is not in the index). We also need an extra check (Using Where) to keep only the rows that match the 2nd condition, too. OK.
Case B (the question)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(thread_id, date_created)
Plan:
Index is used
Using Where
-- no "Using filesort"
So, why does it not need a sort here? Because the index is enough to sort as the query wants. There is of course the additional problem of the extra condition (AND placeholder = FALSE
) which is not covered by the index.
OK but we don't really need a sort here. The index can provide us with results that match the first condition (WHERE thread_id = 12345
) and are in the wanted order for output. The only additional check we need - and what the plan does - is to get the rows from the table, in the order provided by the index, and check this 2nd condition until we get 20 matches. That's what the **Using Where"" means.
We may get the 20 matches in the first 20 rows (so really good and fast) or in the first 100 (still likely fast enough) or in the first 1000000 (probably very, very slow) or we may get just 19 matches from the table even after reading all the matching rows from the index (really very slow on a big table). It all depends on the distribution of data.
Case C (even better plan)
Query:
WHERE thread_id = 12345
AND placeholder = FALSE
ORDER BY date_created DESC
LIMIT 20
Index:
(placeholder, thread_id, date_created)
Plan:
Index is used
-- no "Using Where"
-- no "Using filesort"
Now our index matches both conditions and the order by. The plan is pretty simple: get the first* 20 matches from the index and read the corresponding rows from the table. No extra check (No "Using Where") and no sort (no "Using filesort") needed.
first*: the first 20 when reading the index backwards from the end (as we have ORDER BY .. DESC
) but that's not a problem. B-tree indexes can be read forwards and backwards with almost equal performance.
edited 7 hours ago
answered 8 hours ago
ypercubeᵀᴹypercubeᵀᴹ
79.4k11138225
79.4k11138225
Thank you - this is a great explanation.
– Tom
7 hours ago
add a comment |
Thank you - this is a great explanation.
– Tom
7 hours ago
Thank you - this is a great explanation.
– Tom
7 hours ago
Thank you - this is a great explanation.
– Tom
7 hours ago
add a comment |
Using index indicates a "Covering index" -- All the columns anywhere in theSELECT
are anywhere in the one index. So, you do not have a "covering" index. And it is not practical to make a covering index for your query (too many columns mentioned).
Using where -- mostly noise.
Using filesort -- The query needs a sort, but it might be in RAM or in a temp table. And there may be multiple sorts (eg,GROUP BY x ORDER BY b
)Either of these will make it possible to look only at 20 rows; any other index will require more rows be touched, possibly the entire table:
INDEX(thread_id, placeholder, date_created)
INDEX(placeholder, thread_id, date_created)No, the cardinality of the components of a composite index does not matter when ordering the columns in the index.
My Cookbook explains how to derive the optimal index, given a SELECT
.
add a comment |
Using index indicates a "Covering index" -- All the columns anywhere in theSELECT
are anywhere in the one index. So, you do not have a "covering" index. And it is not practical to make a covering index for your query (too many columns mentioned).
Using where -- mostly noise.
Using filesort -- The query needs a sort, but it might be in RAM or in a temp table. And there may be multiple sorts (eg,GROUP BY x ORDER BY b
)Either of these will make it possible to look only at 20 rows; any other index will require more rows be touched, possibly the entire table:
INDEX(thread_id, placeholder, date_created)
INDEX(placeholder, thread_id, date_created)No, the cardinality of the components of a composite index does not matter when ordering the columns in the index.
My Cookbook explains how to derive the optimal index, given a SELECT
.
add a comment |
Using index indicates a "Covering index" -- All the columns anywhere in theSELECT
are anywhere in the one index. So, you do not have a "covering" index. And it is not practical to make a covering index for your query (too many columns mentioned).
Using where -- mostly noise.
Using filesort -- The query needs a sort, but it might be in RAM or in a temp table. And there may be multiple sorts (eg,GROUP BY x ORDER BY b
)Either of these will make it possible to look only at 20 rows; any other index will require more rows be touched, possibly the entire table:
INDEX(thread_id, placeholder, date_created)
INDEX(placeholder, thread_id, date_created)No, the cardinality of the components of a composite index does not matter when ordering the columns in the index.
My Cookbook explains how to derive the optimal index, given a SELECT
.
Using index indicates a "Covering index" -- All the columns anywhere in theSELECT
are anywhere in the one index. So, you do not have a "covering" index. And it is not practical to make a covering index for your query (too many columns mentioned).
Using where -- mostly noise.
Using filesort -- The query needs a sort, but it might be in RAM or in a temp table. And there may be multiple sorts (eg,GROUP BY x ORDER BY b
)Either of these will make it possible to look only at 20 rows; any other index will require more rows be touched, possibly the entire table:
INDEX(thread_id, placeholder, date_created)
INDEX(placeholder, thread_id, date_created)No, the cardinality of the components of a composite index does not matter when ordering the columns in the index.
My Cookbook explains how to derive the optimal index, given a SELECT
.
answered 6 hours ago
Rick JamesRick James
44.8k22462
44.8k22462
add a comment |
add a comment |
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f240742%2fcovering-index-used-despite-missing-column%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown