create database task250;
use task250;
CREATE TABLE Students (
id INT PRIMARY KEY AUTO_INCREMENT,
firstname VARCHAR(50),
lastname VARCHAR(50),
department VARCHAR(50)
);
CREATE TABLE Subjects (
id INT PRIMARY KEY AUTO_INCREMENT,
subject_name VARCHAR(100)
);
CREATE TABLE Marks (
student_id INT,
subject_id INT,
marks DECIMAL(5, 2),
PRIMARY KEY (student_id, subject_id),
FOREIGN KEY (student_id) REFERENCES Students(id),
FOREIGN KEY (subject_id) REFERENCES Subjects(id)
);
CREATE INDEX idx_firstname ON Students(firstname);
CREATE INDEX idx_subject_name ON Subjects(subject_name);
CREATE INDEX idx_department ON Students(department);
CREATE INDEX idx_firstname ON Students(firstname);
CREATE INDEX idx_subject_name ON Subjects(subject_name);
CREATE INDEX idx_department ON Students(department);
SET @searchKey = 'Mana%';
SELECT * FROM (
SELECT s.id, s.firstname, s.lastname, s.department, sub.subject_name, m.marks
FROM Students s
JOIN Marks m ON s.id = m.student_id
JOIN Subjects sub ON m.subject_id = sub.id
WHERE s.department LIKE @searchKey
LIMIT 10000
) AS dept_results
UNION all
SELECT * FROM (
SELECT s.id, s.firstname, s.lastname, s.department, sub.subject_name, m.marks
FROM Students s
JOIN Marks m ON s.id = m.student_id
JOIN Subjects sub ON m.subject_id = sub.id
WHERE s.firstname LIKE @searchKey
LIMIT 10000
) AS name_results
UNION all
SELECT * FROM (
SELECT s.id, s.firstname, s.lastname, s.department, sub.subject_name, m.marks
FROM Students s
JOIN Marks m ON s.id = m.student_id
JOIN Subjects sub ON m.subject_id = sub.id
WHERE sub.subject_name LIKE @searchKey
LIMIT 1000
) AS subject_results
ORDER BY
CASE
WHEN firstname LIKE @searchKey THEN 1 -- Names starting with searchKey first
WHEN firstname LIKE CONCAT('%', @searchKey, '%') THEN 2 -- Names containing searchKey anywhere next
ELSE 3
END,
firstname
LIMIT 10000;
I have 250k records in the database.
API response time acccording to different character searching lengths.
UNION runs three requests in parallel to save time.
How can I get fetch time on my local system under 100ms even for one character?
create database task250;
use task250;
CREATE TABLE Students (
id INT PRIMARY KEY AUTO_INCREMENT,
firstname VARCHAR(50),
lastname VARCHAR(50),
department VARCHAR(50)
);
CREATE TABLE Subjects (
id INT PRIMARY KEY AUTO_INCREMENT,
subject_name VARCHAR(100)
);
CREATE TABLE Marks (
student_id INT,
subject_id INT,
marks DECIMAL(5, 2),
PRIMARY KEY (student_id, subject_id),
FOREIGN KEY (student_id) REFERENCES Students(id),
FOREIGN KEY (subject_id) REFERENCES Subjects(id)
);
CREATE INDEX idx_firstname ON Students(firstname);
CREATE INDEX idx_subject_name ON Subjects(subject_name);
CREATE INDEX idx_department ON Students(department);
CREATE INDEX idx_firstname ON Students(firstname);
CREATE INDEX idx_subject_name ON Subjects(subject_name);
CREATE INDEX idx_department ON Students(department);
SET @searchKey = 'Mana%';
SELECT * FROM (
SELECT s.id, s.firstname, s.lastname, s.department, sub.subject_name, m.marks
FROM Students s
JOIN Marks m ON s.id = m.student_id
JOIN Subjects sub ON m.subject_id = sub.id
WHERE s.department LIKE @searchKey
LIMIT 10000
) AS dept_results
UNION all
SELECT * FROM (
SELECT s.id, s.firstname, s.lastname, s.department, sub.subject_name, m.marks
FROM Students s
JOIN Marks m ON s.id = m.student_id
JOIN Subjects sub ON m.subject_id = sub.id
WHERE s.firstname LIKE @searchKey
LIMIT 10000
) AS name_results
UNION all
SELECT * FROM (
SELECT s.id, s.firstname, s.lastname, s.department, sub.subject_name, m.marks
FROM Students s
JOIN Marks m ON s.id = m.student_id
JOIN Subjects sub ON m.subject_id = sub.id
WHERE sub.subject_name LIKE @searchKey
LIMIT 1000
) AS subject_results
ORDER BY
CASE
WHEN firstname LIKE @searchKey THEN 1 -- Names starting with searchKey first
WHEN firstname LIKE CONCAT('%', @searchKey, '%') THEN 2 -- Names containing searchKey anywhere next
ELSE 3
END,
firstname
LIMIT 10000;
I have 250k records in the database.
API response time acccording to different character searching lengths.
UNION runs three requests in parallel to save time.
How can I get fetch time on my local system under 100ms even for one character?
Share Improve this question edited Mar 3 at 18:51 Dale K 27.5k15 gold badges58 silver badges83 bronze badges asked Mar 3 at 9:32 Shameer AliShameer Ali 11 8 | Show 3 more comments1 Answer
Reset to default 0Few things...
First, remove your duplicate indexes, not sure why they are there, probably copy paste or AI confusion?
CREATE INDEX idx_firstname ON Students(firstname);
CREATE INDEX idx_subject_name ON Subjects(subject_name);
CREATE INDEX idx_department ON Students(department);
CREATE INDEX idx_firstname ON Students(firstname);
CREATE INDEX idx_subject_name ON Subjects(subject_name);
CREATE INDEX idx_department ON Students(department);
Further, you should add FULLTEXT indexes on the fields instead even, for example :
ALTER TABLE Students ADD FULLTEXT idx_fulltext_firstname (firstname);
Then utilize Match() Against() which is significantly faster:
WHERE MATCH(s.firstname) AGAINST (@searchKey IN BOOLEAN MODE)
Rinse and repeat for your other fields...
Let me know how it works out and I'll reply if this doesn't do the trick =)
LIMIT
withoutORDER BY
is a code smell. What is the logic for determining which 1000 records are being returned? Currently, MySQL may return any random 1000 records. – Tim Biegeleisen Commented Mar 3 at 9:50WHERE something LIKE @searchKey
you can get anything from no rows at all to all rows in the table, and you can't index either, because @searchKey can be anything. Disk defragmentation may be a solution to provide a quicker full table scan. But if you want this type of query really fast, invest in hardware. – Thorsten Kettner Commented Mar 3 at 10:37