Как оптимизировать этот sqlrq? Это правильно? Как сделать лучше? - PullRequest
0 голосов
/ 08 января 2019

Спасибо за ваше внимание. Всю ночь старался изо всех сил, но безрезультатно. Я новичок в MySQL.


Пожалуйста, скажи мне правильно ли он построен и оптимизирован:

SELECT * 
FROM (
    (`tbl_projects` 
LEFT JOIN `tbl_files` 
    ON ((`file_isforType` = 1) AND `file_isforID`=`proj_uid`) )
INNER JOIN `tbl_users` 
    ON `proj_InitiatorUsrID` = `usr_UID` )
ORDER BY `file_uid` DESC LIMIT 0 , 15

Я использовал EXPLAIN на нем и обнаружил, что он не использует какой-либо ключ для первой таблицы table_projects.

Я положил туда скриншот =

enter image description here


Идея базы данных следующая. Любой пользователь может опубликовать любое количество проектов и каждый проект может иметь свои картинки (0..x)

проект МОЖЕТ ИМЕТЬ прикрепленный файл. может иметь 1 или несколько или может не иметь.


совместное следующее: файлы проекта внутри пользователя. Файлы пользователя слева

Что я получаю по этому rq:

proj1 | user1 | photo1
proj1 | user1 | photo2
proj1 | user1 | photo3

proj2 | user1 | photo4
proj2 | user1 | photo5

proj3 | user2 | photo6

proj4 | user1 | null

proj5 | user1 | photo7
proj5 | user1 | photo8
proj6 | user2 | null

так по порядку сверху вниз мой php скрипт формы в html списке проектов. у некоторых нет фотографий. у некоторых есть один. у некоторых 2,3,4 .. и т. д.

proj1 - user1 - 3 photos
proj2 - user1 - 2 photos
proj3 - user2 - 1 photo
proj4 - user1 -  no photos
proj5 - user1 - 2 photos
etc

table_files строится в следующей логике:

file_uid | file_ownerID | file_isforType| file_isforID
file_uid PRIMARY AI
file_ownerID  reference to PRIMARY at table_users
file_isforType- smallint 1..9
indicates type of THING which this file was attached to.
 eg
1 = _TheProject as project photo
2 = _TheUserProfile as users photo
3 = _TheMessage as attachment

file_ResourceID - unique id of that very thing, whose type specified in file_isforType.

например

if (file_isWhatfor=_TheProject) AND (file_ResourceID=3)    ->> to the proj#3
if (file_isWhatfor=_TheUserProfile) AND (file_ResourceID=3)    ->> to the user#3
if (file_isWhatfor=_TheMessage) AND (file_ResourceID=3)    ->> to the msg#3

1 Ответ

0 голосов
/ 08 января 2019

Мы не можем знать, «оптимизировано» ли это, потому что для этого нужно знать больше, чем вы нам сказали. Подробнее об этом позже.

В то время как MySQL разрешает использовать обратные метки для идентификаторов, вы не обязаны использовать их, ЕСЛИ БЕЗ идентификатора не содержит пробела или является зарезервированным словом. Что необходимо, так это добавить префиксы имен столбцов к именам таблиц ИЛИ использовать вместо них псевдонимы таблиц. Это настоятельно рекомендуется (т. Е. «Наилучшая практика»), чтобы вы всегда знали, из какой таблицы происходит столбец. Заметьте, что мне пришлось УБЕДИТЬ, какой псевдоним таблицы использовать во всех соединениях, приведенных ниже, они могут нуждаться в исправлении.

SELECT 
       *
FROM   tbl_projects AS p
LEFT JOIN tbl_files AS f ON p.proj_uid = f.file_isforID AND f.file_isforType = 1
INNER JOIN tbl_users AS u ON p.proj_InitiatorUsrID = u.usr_UID
ORDER BY f.file_uid DESC 
LIMIT 0 , 15

Обратите также внимание, что все используемые вами скобки полностью избыточны и могут быть безопасно удалены.

Для дальнейшей "оптимизации" я предлагаю вам НЕ использовать select *. Укажите нужные столбцы, это может повысить скорость передачи результатов, но не обязательно оказывает какое-либо измеримое влияние на выполнение запроса. Помимо этого вам нужно иметь индексы для всех столбцов, участвующих во всех объединениях, и вы можете узнать, отсутствуют ли индексы, используя explain plan. См. 8.8.1 Оптимизация запросов с помощью EXPLAIN

Если индекс отсутствует, рассмотрите возможность добавления его в таблицу, указанную в объяснении.

...