SQL query MATCH with alias and order by and optimize query - mysql

i'm using this query to search inside table:
SELECT
*,
MATCH(tags,title,description)
AGAINST ('hey you are you in' IN BOOLEAN MODE) AS score
FROM table
ORDER BY insert_datetime DESC, id DESC
what i need is to use the alias 'score' to order results, is this the right sintax?:
SELECT
*,
MATCH(tags,title,description)
AGAINST ('hey you are you in' IN BOOLEAN MODE) AS score
FROM table
ORDER BY score DESC, insert_datetime DESC, id DESC
is also there anyway to optimize this query ? better way to write that?

is this the right sintax?
Yes. As documented under SELECT Syntax:
A select_expr can be given an alias using AS alias_name. The alias is used as the expression's column name and can be used in GROUP BY, ORDER BY, or HAVING clauses.
is also there anyway to optimize this query ? better way to write that?
If you don't need the relevance score in your resultset, you need not select it:
SELECT *
FROM table
ORDER BY MATCH(tags, title, description) AGAINST (
'hey you are you in' IN BOOLEAN MODE
) DESC, insert_datetime DESC, id DESC
But sadly, as suggested under ORDER BY Optimization, there is no way that MySQL can avoid undertaking a filesort when ordering by the result of a function such as MATCH() ... AGAINST():
In some cases, MySQL can use an index to satisfy an ORDER BY clause without doing any extra sorting.
The index can also be used even if the ORDER BY does not match the index exactly, as long as all of the unused portions of the index and all the extra ORDER BY columns are constants in the WHERE clause.
However, one could:
filter the resultset for only those records of interest by using a WHERE clause, thereby reducing the number of results that must be sorted; and/or
reduce the maximum number of comparisons each sorting step will need to perform by removing unneeded columns from the ORDER BY clause.

Related

MySQL ORDER BY CASE optimization

I looked over the internet, but I couldn't find a solution for this particular query. I have this query:
SELECT *
FROM profile
ORDER BY CASE WHEN country_geoname_id = 2635167
THEN 1 ELSE 0 END DESC,
score DESC
I want to know if it's possible to optimize this query by avoiding the filesort. I created an index for the columns (country_geoname_id and score), but it didn't help.
EXPLAIN SELECT:
You make your order condition not sargeable when put it inside a function.
What makes a SQL statement sargable?
if you want use index create an aditional boolean field isMyCountry and create an index for it
Then your query became:
SELECT *
FROM profile
ORDER BY isMyCountry,
score DESC

MySQL GROUP BY order when no ORDER BY

In MySQL, what order is the resultset if GROUP BY is used but ORDER BY is not specified?
I have inherited code with queries like:
SELECT col1, COUNT(col1)
FROM table
GROUP BY col1
(Actually the SELECT statement can be much more complex than that, involving JOINs etc., but let's start with the base principle.) Note that there is no ORDER BY.
In, say, SQL Server BOL, I am told:
The GROUP BY clause does not order the result set. Use the ORDER BY
clause to order the result set.
I have been unable to find a statement as to whether MySQL GROUP BY does or does not promise a particular ordering from GROUP BY alone? If a MySQL reference could be provided to back up any answer that would be most welcome.
From the manual:
If you use GROUP BY, output rows are sorted according to the GROUP BY
columns as if you had an ORDER BY for the same columns. To avoid the
overhead of sorting that GROUP BY produces, add ORDER BY NULL:
SELECT a, COUNT(b) FROM test_table GROUP BY a ORDER BY NULL;
Relying on implicit GROUP BY sorting (that is, sorting in the absence
of ASC or DESC designators) is deprecated. To produce a given sort
order, use explicit ASC or DESC designators for GROUP BY columns or
provide an ORDER BY clause.

Why can't MySQL use an index for ORDER BY if ASC and DESC are mixed?

Let's say I have a very simple table like this:
CREATE TABLE `t1` (
`key_part1` INT UNSIGNED NOT NULL,
`key_part2` INT UNSIGNED NOT NULL,
`value` TEXT NOT NULL,
PRIMARY KEY (`key_part1`, `key_part2`)
) ENGINE=InnoDB
Using this table, I want to issue a query like this:
SELECT *
FROM `t1`
ORDER BY `key_part1` ASC, `key_part2` DESC
LIMIT 1
I had hoped that the ORDER BY in this query would get satisfied by the index. However, according to the MySQL documentation:
In some cases, MySQL cannot use indexes to resolve the ORDER BY, although it still uses indexes to find the rows that match the WHERE clause. These cases include the following:
You mix ASC and DESC:
SELECT * FROM t1 ORDER BY key_part1 DESC, key_part2 ASC;
I tried a query similar to the above query and as expected, the EXPLAIN output says that such a query does a filesort. This doesn't totally make sense to me because I can do the following:
SELECT *
FROM `t1`
WHERE `key_part1` = (
SELECT `key_part1`
FROM `t1`
ORDER BY `key_part1` ASC
LIMIT 1
)
ORDER BY `key_part2` DESC
LIMIT 1
When I EXPLAIN this, it says both the subquery and the outer query do not use a filesort. Furthermore, I tried this kind of trick big table I have with a similar structure and found that it speeds up my query by 3 orders of magnitude.
My questions are
Are the two queries I show here equivalent? They seem like they are, but I may be missing something. If they are not, what kind of data would I need to have in my table to cause them to give different results?
Is there a reason that MySQL can't do this optimization trick on it's own, or is this just a case of an optimization that is possible, but just hasn't been written into MySQL?
If it matters, I am using MySQL 5.6.22.
Further clarification:
By "equivalent" I mean "produce the same result". Additionally, I am very aware that if I were to change LIMIT 1 to LIMIT 2 or something, the queries would no longer produce the same results. I am not interested in those cases, only in the case with LIMIT 1.
It's not that MySQL is missing an optimization "trick", it's a property of how compound indexes work. MySQL can only do an index scan in one direction at a time, and has to go with how the index is ordered (so it can do computer-sciency things like binary search, etc).
Let's look at your sample query:
SELECT *
FROM t1
WHERE key_part1 = (
SELECT key_part1
FROM t1
ORDER BY key_part1 ASC
LIMIT 1
)
ORDER BY key_part2 DESC
LIMIT 1
This can order on key_part2 because all returned rows will have an identical key_part1. So basically mysql can ignore that part of the index; it is functionally identical to ORDER BY key_part1 DESC, key_part2 DESC. The direction of the ORDER BY in your subquery is irrelevant because it was in a subquery.
Edit
To be clear, your example query really looks like this:
SELECT *
FROM t1
WHERE key_part1 = #{some value}
ORDER BY key_part2 DESC
LIMIT 1
Where #{some value} is the result of a subselect. It should be clear now why this sort doesn't need a filesort, because you are not sorting by key_part1 at all. In fact, there is no need to, because all returned rows will have identical key_part1.

Order by performance problems

I have an index problem with my order by statement. I have this query witch is runing fast:
SELECT name from members where kat = 2 order by date DESC;
I have a composite index on members table:
kat_index(kat,date);
Now my aplication has changed and i have added a query like this:
SELECT name from members where kat = 2 order by logged_in DESC, status DESC, date DESC;
Now the query i slow because it's using filesort. So the question is... What type of index should i add to satisfy both queries?
You should have two indexes:
(kat, date)
(kat, logged_in, status, date)
Each query will use the index that is best for that query.
You cannot cover both queries with one index. You must form a leftmost prefix on the composite index along with the ORDER BY clause as well.

MySQL not using indexes; using filesort

MySQL appears to be not using indexes and is using filesort on the following query:
SELECT `tweets`.*
FROM `tweets`
WHERE (`tweets`.contest_id = 159)
ORDER BY tweet_id ASC, tweeted_at DESC LIMIT 100 OFFSET 0
I have indexes on contest_id, tweet_id and tweeted_at
When I execute EXPLAIN EXTENDED, Extra returns "Using where; using filesort". How can I improve my query?
When you mix ASC and DESC sorting, MySQL cannot use indexes to optimize the GROUP BY statement.
Also, using multiple keys to sort will result in it not being able to optimize the query with indexes.
From the docs:
http://dev.mysql.com/doc/refman/5.6/en/order-by-optimization.html
In some cases, MySQL cannot use
indexes to resolve the ORDER BY,
although it still uses indexes to find
the rows that match the WHERE clause.
These cases include the following:
You use ORDER BY on different keys:
SELECT * FROM t1 ORDER BY key1, key2;
...
You mix ASC and
DESC:
SELECT * FROM t1 ORDER BY key_part1
DESC, key_part2 ASC;
If the two columns you are ordering on are not part of the same key, then you are doing both of the above things.