Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

trifek's avatar

Mysql query with ordering in mysql is very slow

Hi, I have problem with my sql query.

I have table:

CREATE TABLE `psUploadedFiles` (
  `id_uploaded_files` int(10) UNSIGNED NOT NULL,
  `enable` char(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
  `company_id` int(11) NOT NULL DEFAULT '0',
  `id_user` int(11) NOT NULL DEFAULT '0',
  `file_path` varchar(150) COLLATE utf8_unicode_ci NOT NULL,
  `file_name` varchar(75) COLLATE utf8_unicode_ci NOT NULL,
  `number` bigint(20) NOT NULL DEFAULT '0',
  `enum` int(11) NOT NULL DEFAULT '0',
  `category` int(11) NOT NULL DEFAULT '0',
  `type` char(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
  `html_code` text COLLATE utf8_unicode_ci,
  `creation_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `description` text COLLATE utf8_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

CREATE TABLE `psEventsCalendar` (
  `id_events_calendar` int(11) UNSIGNED NOT NULL,
  `id_category_page` int(11) NOT NULL DEFAULT '0',
  `enable` char(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
  `title` varchar(80) COLLATE utf8_unicode_ci DEFAULT NULL,
  `date` date NOT NULL,
  `file` varchar(120) COLLATE utf8_unicode_ci DEFAULT NULL,
  `visible_on_the_front` char(1) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0',
  `hour` varchar(15) COLLATE utf8_unicode_ci DEFAULT NULL,
  `description` mediumtext COLLATE utf8_unicode_ci,
  `id_localization` int(11) NOT NULL DEFAULT '0',
  `url_address_pl` varchar(125) COLLATE utf8_unicode_ci DEFAULT NULL,
  `price` varchar(25) COLLATE utf8_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

ALTER TABLE `psEventsCalendar`
  MODIFY `id_events_calendar` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=578;

ALTER TABLE `psEventsCalendar`
  ADD PRIMARY KEY (`id_events_calendar`);

ALTER TABLE `psUploadedFiles`
  MODIFY `id_uploaded_files` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=23503;

ALTER TABLE `psUploadedFiles`
  ADD PRIMARY KEY (`id_uploaded_files`);

When I run my query:

SELECT id_events_calendar, url_address_pl, title AS title,  title AS description,  title AS keywords,  hour, date,
       (SELECT CONCAT(file_path, '/', file_name) AS image FROM psUploadedFiles B WHERE category = A.id_events_calendar and enum=14 ORDER by number LIMIT 1) AS image
FROM psEventsCalendar A WHERE visible_on_the_front = '1' and enable = '1' ORDER BY RAND()LIMIT 10;

Is veery slow. How can I fix it?

I need show records with events (psEventsCalendar) with first image prepared for this event (psUploadedFiles). How can I make it's better?

0 likes
8 replies
LaryAI's avatar
Level 58

The slowness of your query could be due to a few reasons:

  1. The subquery in the SELECT clause is executed for each row in the psEventsCalendar table. This can be very slow if the table has many rows.
  2. The ORDER BY RAND() clause can be very slow because it requires a full table scan and a sort.
  3. There might be missing indexes on the columns used in the WHERE and ORDER BY clauses.

Here are a few suggestions to improve the performance:

  1. Instead of using a subquery in the SELECT clause, you can use a JOIN to the psUploadedFiles table. This will allow MySQL to execute the join operation more efficiently.

  2. Instead of using ORDER BY RAND(), you can use a different method to randomize the results. One common method is to generate a random number in your application, and use it as an offset in the LIMIT clause.

  3. Make sure you have indexes on the columns used in the WHERE and ORDER BY clauses. In this case, you should have indexes on psEventsCalendar.visible_on_the_front, psEventsCalendar.enable, and psUploadedFiles.category.

Here is an example of how you can rewrite your query:

SELECT 
    A.id_events_calendar, 
    A.url_address_pl, 
    A.title AS title,  
    A.title AS description,  
    A.title AS keywords,  
    A.hour, 
    A.date,
    CONCAT(B.file_path, '/', B.file_name) AS image 
FROM 
    psEventsCalendar A 
LEFT JOIN 
    (SELECT * FROM psUploadedFiles WHERE enum=14 ORDER BY number LIMIT 1) B 
ON 
    A.id_events_calendar = B.category 
WHERE 
    A.visible_on_the_front = '1' 
    AND A.enable = '1' 
ORDER BY 
    A.id_events_calendar 
LIMIT 10 OFFSET RAND()*(SELECT COUNT(*) FROM psEventsCalendar);

Please note that the RAND() function in the OFFSET clause is a placeholder. You should replace it with a random number generated in your application. Also, the subquery in the LEFT JOIN clause assumes that the psUploadedFiles table is not very large. If it is, you might need to find a different way to select the first image for each event.

trifek's avatar

@laryai this query is not working. It's not return image - it's return only events

vincent15000's avatar

I notice that you don't have indexed any field.

You should add an index on the fields used to order the results.

trifek's avatar

@vincent15000 you think about something like this: create index idx on psUploadedFiles (enum, number); ?

1 like
vincent15000's avatar
Level 63

@trifek I mean something like this.

CREATE INDEX index_name ON table_name (column_name);

Only one column for each index is better ;).

Tray2's avatar

@vincent15000 This is not true, it depends on the the queries that you run.

Only one column for each index is better ;).

A composite index might be a better choice, since it would give a single index, rather than multiple indexes for the same table.

Indexes are the trickiest thing to balance when it comes to high performance databases.

1 like
vincent15000's avatar

@Tray2 Yes I agree, sure it depends on the query, I should have explained why I said that, sorry.

1 like

Please or to participate in this conversation.