Laravel Model query is slow, but fast on MySQL? - php

I have a table in my database with approx 400K rows, and I am executing the following statement (query that laravel is executing):
select * from `activities` where `device_id` = ? and `battery_level` is not null order by `created_at` desc limit 1
This takes less than 100ms when I execute it directly using a MySQL client. But laravel takes 1,5 - 2 seconds
My table looks like this:
And how I use the models: (takes 1500ms)
Activity::query()
->where('device_id', 288)
->whereNotNull('battery_level')
->orderByDesc('created_at')
->first();
And with DB: (also takes 1500 ms)
DB::table('activities')
->where('device_id', 288)
->whereNotNull('battery_level')
->orderByDesc('created_at')
->first();
I am looking to reduce this query to the same speed as MySQL between 100 and 200ms max. Removing the ordering desc reduces the time of the query, but I need to use order desc to get the latest.
Any idea what I am doing wrong here?

It may be helpful to provide SHOW CREATE TABLE.
Replacing INDEX(device_id) by
INDEX(device_id, battery_leve, created_at)
may help.

Try this:
$record = DB::raw("SELECT * FROM activities WHERE device_id = 1 AND battery_level IS NOT NULL ORDER BY created_at DESC LIMIT 1")

Related

MySQL out of sort memory

I have data in MYSQL table where i have to paginate through 4 rows at a time.
To do this I use the command below where i increase X from 0 by 4 until i reach the end of the data.
The command works for X=0 and X=4, when i reach X=8 i get the error #1038 - out of sort memory, i tried increasing it to 256K but same result.
Anybody know how to solve? Im using PHP
SELECT DISTINCT * FROM ((SELECT DISTINCT * FROM table WHERE (scope=0) AND (id='6')) UNION (SELECT DISTINCT * FROM table WHERE (scope=0) AND (id<=1000))) as total ORDER BY timestamp DESC LIMIT X,4
Not an answer, but your query seems to be functionally identical to this:
SELECT columns
, you
, actually
, want
FROM table
WHERE scope = 0
AND id<=1000
ORDER
BY timestamp DESC
LIMIT X,4

What is a less expensive alternative to "mysqli_query(SELECT count(*) from table where created_at > $time"

I have a script that I need to run in under 1 second. I have this line that takes 4.4 seconds on average to execute.
$result = mysqli_query($conn, "SELECT count(*) from record where created_at > '$time'");
The rest of the script takes less than 0.1 second.
I aggree with #xQbert and wonder if COUNT(1) or COUNT(ID) could increase speed... but nevermind...
Edit - just had the answer
Count(*) vs Count(1)
You should add an index involving created_at row. Try to add a UNIQUE INDEX on created_at if possible or on created_at and another row (i.e. created_at + user_id). The more restrictive you will be, the faster you will get your results.
Another point is, if you only need 5 results... limit your query with LIMIT 0,5
Believe me... PHP won't be faster than MySQL! ;)

How to optimize query to avoid timeout on mysql/php connection

I recently design a php/mysql website.
I the index page I used this sql query
SELECT * FROM upload WHERE aid = '206' AND pin = '0' AND format like '%video%' ORDER BY created DESC
SELECT * FROM upload WHERE aid = '206' AND pin = '0' AND format like '%image%' ORDER BY created DESC
SELECT * FROM upload WHERE aid = '206' AND pin = '0' AND format like '%image%' ORDER BY created DESC
I do not have a big data yet...maybe 1000 records in DB.
But when I load the page..it takes 8-20 seconds to load.
when I remove that sal queries,the load time will be normal.
please advice me best method to resolve that.
You are using 3 different SQL queries to get the data from same table.
You can get the same result using only one SQL query.
So SQL query should be as below.
SELECT * FROM `upload` WHERE `aid` = '206' AND `pin` = '0' AND (`format` like '%video%' OR `format` like '%image%') ORDER BY `created` DESC
There may be chances that you might have included many CSS,Images or JavaScript libraries.
You can check your page performance issue using below site.
http://tools.pingdom.com/fpt/
Things that might be worth trying to speed things up:
add appropriate indexes to your table (perhaps aid should be an index?)
combine these three queries into a single query (as per Ali Khanusiya's answer)
add an appropriate LIMIT clause to your query (eg. LIMIT 1 or LIMIT 10) to fetch a subset of the results (you can use an OFFSET to paginate the results)

Query need optimizing or do I just need higher max connections?

I have a mysql database. My site has been getting a lot of max_user_connections errors, and since I can't increase the limit for a few more days, I was wondering if you guys could help me optimize this query that's taking between 1 and 4 seconds to complete. The 'status' table is InnoDB with 230,221 rows, and there are indexes already on it, but is it just a poorly written query?
SELECT status.id,users.id
FROM users, status
WHERE clan='someClan'
AND status.author!='loggedInUser'
AND status.anonymous!='someUser'
AND users.username='someUser'
AND status.data!=''
AND status.postdate > users.news_read
GROUP BY postdate LIMIT 2
Thank you for any help.
You need to provide the proper connection between the users and the status table. Right now you are returning size(users table) * size(status table) number of rows.
From your comments, let me assume that you know the current user's users.id.
SELECT status.id
FROM status
WHERE status.clan='someClan' \\ assuming clan is in status table
AND status.author!='someUser'
AND status.anonymous!='someUser'
AND status.data!=''
AND status.postdate > (Select users.news_read
from users
where users.username='someUser'
)
GROUP BY postdate LIMIT 2

mysql heavy RAND query alternatives

I have query that gets 10 random posts , and as you know this is very slow and heavy query, is there any alternatives to submit this query without any slow appearance?
my current rand query :
SELECT * FROM posts ORDER BY RAND() LIMIT 10
From MySQL document:
SELECT * FROM tablename ORDER BY RAND() LIMIT 1
works for small tables, but once the tables grow larger than 300,000 records or so this will be very slow because MySQL will have to process ALL the entries from the table, order them randomly and then return the first row of the ordered result, and this sorting takes long time. Instead you can do it like this (atleast if you have an auto_increment PK):
SELECT MIN(id), MAX(id) FROM tablename;
Fetch the result into $a
//php code
$id=rand($a[0],$a[1]);
SELECT * FROM tablename WHERE id>='$id' LIMIT 1

Categories