Я не эксперт по БД, поэтому некоторое время я был там, читая столько, сколько могу, и благодаря ответам сообщества я мог внести несколько изменений в свой запрос и структуру таблиц. Даже после прочтения многих вещей я застрял, поэтому я пришел, чтобы задать свой первый вопрос.
У меня есть сайт, где пользователи публикуют свои истории. Каждая история может иметь жанры, предупреждения, нескольких авторов, назначенных нескольких символов и т. Д.
Мы работаем с MySQL 5.x, таблицы InnoDB, сайт написан на PHP. Использование GROUP_CONCAT для возврата одной строки на историю в результате. Пробовал ранее использовать идентификатор истории GROUP BY, но каждый запрос занимал около 16 секунд, был очень медленным. С этим новым они занимают 0,175, но, например, если жанр в WHERE не существует, запрос занимает 23 секунды! Для тестов каждая таблица имеет 1 миллион записей, таблица авторов - 1,5 миллиона. Я попытался разместить несколько дополнительных индексов, чтобы увидеть, какой MySQL будет использовать.
Я пытался нормализовать отношения между людьми. Здесь я представлю только несколько таблиц, поскольку решение, вероятно, охватит всю проблему. Любая помощь с благодарностью, спасибо за ваше время!
Таблица
CREATE TABLE `fanfiction_authors` (
`uid` int(11) NOT NULL AUTO_INCREMENT,
`penname` varchar(100) NOT NULL,
`penname_url` varchar(100) NOT NULL,
PRIMARY KEY (`uid`),
KEY `penname_url` (`penname_url`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1000000 ;
-- --------------------------------------------------------
CREATE TABLE `fanfiction_stories` (
`sid` int(11) NOT NULL AUTO_INCREMENT,
`title` varchar(200) NOT NULL,
`sinopse` text NOT NULL,
PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1000000 ;
-- --------------------------------------------------------
CREATE TABLE `fanfiction_stories_authors` (
`sid` int(11) NOT NULL,
`uid` int(11) NOT NULL,
KEY `sid_uid` (`sid`,`uid`),
KEY `sid` (`sid`),
KEY `uid` (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
CREATE TABLE `fanfiction_stories_genres` (
`key_id` int(11) NOT NULL AUTO_INCREMENT,
`sid` int(11) NOT NULL,
`genre_id` int(11) NOT NULL,
PRIMARY KEY (`key_id`),
KEY `sid` (`sid`),
KEY `genre_id` (`genre_id`),
KEY `sid_genreid` (`sid`,`genre_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1000000 ;
-- --------------------------------------------------------
CREATE TABLE `fanfiction_stories_stats` (
`sid` int(11) NOT NULL,
`reviews` int(11) NOT NULL,
`recomendacoes` int(11) NOT NULL,
PRIMARY KEY (`sid`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
-- --------------------------------------------------------
CREATE TABLE `fanfiction_stories_warnings` (
`key_id` int(11) NOT NULL AUTO_INCREMENT,
`sid` int(11) NOT NULL,
`warning_id` int(11) NOT NULL,
PRIMARY KEY (`key_id`),
KEY `sid` (`sid`),
KEY `warning_id` (`warning_id`),
KEY `warningid_sid` (`sid`,`warning_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1000000 ;
----
Запрос
SELECT
st.sid, st.title, st.sinopse,
(SELECT GROUP_CONCAT(CAST(genre_id AS CHAR)) FROM fanfiction_stories_genres WHERE sid = st.sid) as genres,
stats.reviews, stats.recomendacoes,
(SELECT GROUP_CONCAT(CAST(warning_id AS CHAR)) FROM fanfiction_stories_warnings WHERE sid = st.sid) as warnings_ids
FROM
fanfiction_stories AS st
LEFT JOIN fanfiction_stories_stats AS stats ON st.sid = stats.sid
WHERE
st.sid IN (SELECT sid FROM fanfiction_stories_warnings WHERE warning_id = 5) AND
st.sid IN (SELECT sid FROM fanfiction_stories_genres WHERE genre_id = 300)
ORDER BY
st.sid ASC
LIMIT 20
Я не мог сделать мое объяснение читаемым здесь, поэтому я загрузил экран печати в Dropbox. Не удалось вставить изображение, потому что я нуб, извините.
Это объяснение расширяется, когда у нас есть действующий жанр (Вы найдете истории с жанром номер 300).
http://dl.dropbox.com/u/14508898/Printscreen/stackoverflow_explain_print_001.PNG
Это объяснение расширяется, когда у нас есть недопустимый жанр (Вы НЕ найдете историй с жанром номер 900).
http://dl.dropbox.com/u/14508898/Printscreen/stackoverflow_explain_print_002.PNG
Не могли бы вы, ребята, помочь мне, пожалуйста? Правильна ли моя нормализация? Что я делаю не так?
Заранее спасибо!