2013-05-09 7 views
1

Я использую базу данных MySQL world.sql. Именно то, что в нем не имеет значения, но схема, которая имеет значение для использования выглядит следующим образом:Ускорение медленного SQL-запроса

CREATE TABLE city (
    name char(35), 
    country_code char(3), 
    population int(11), 
); 
CREATE TABLE country (
    code char(3), 
    name char(52), 
    population int(11) 
); 

Запрос на вопрос, на английском языке, «для каждой страны, дать мне свое имя и население, наряду с название и население для города, который имеет самое высокое отношение населения к численности населения страны»

в настоящее время у меня есть следующий SQL:

SELECT t.name, t.population, c.name, c.population 
FROM country c 
JOIN city t 
ON t.country_code = c.code 
WHERE t.population/c.population = (
    SELECT MAX(tt.population/c.population) 
    FROM city tt 
    WHERE t.country_code = tt.country_code 
) 

в настоящее время запрос занимает около 10 минут, чтобы работать на моем SQLite база данных. База данных world.sql невелика (4000-5000 строк?), Поэтому я предполагаю, что я делаю что-то неправильно здесь.

В настоящее время у меня нет ни одного индекса или ничего: база данных представляет собой пустую базу данных с данным набором данных (https://dl.dropboxusercontent.com/u/7997532/world.sql). Может ли кто-нибудь дать мне какие-либо указания относительно того, что мне нужно исправить, чтобы заставить его работать в течение разумного промежутка времени?

EDIT: ну вот еще один поворот на вопрос:

Это работает в < 2 секунды

SELECT t.name, t.population, c.name, c.population 
    FROM country c 
    JOIN city t 
    ON t.country_code = c.code 
    WHERE t.population * 1.0/c.population = (
     SELECT MAX(tt.population * 1.0/c.population) 
     FROM city tt 
     WHERE tt.country_code = t.country_code 
    ) 

Хотя это займет 10 минут, чтобы запустить

SELECT t.name, t.population, c.name, c.population 
    FROM country c 
    JOIN city t 
    ON t.country_code = c.code 
    AND t.population * 1.0/c.population = (
     SELECT MAX(tt.population * 1.0/c.population) 
     FROM city tt 
     WHERE tt.country_code = t.country_code 
    ) 

Является ли решение затем просто как можно больше вставляйте предложение ON, когда я делаю JOINs? Кажется, в этом случае я могу уйти без индекса, если я это сделаю ...

+0

Вы можете попробовать сделать указатель на city.country_code и country.code и посмотреть, ускоряет ли он его. – Patashu

ответ

0

В идеале я бы сначала начал с индексов и рассмотрел возможность добавления вычисленного поля, которое предварительно вычисляет t.population/c.population в таблица ссылок

Таким образом, для каждой страны и города вы можете найти его соотношение населения, не вычислив его в RBAR.

+0

RBAR означает «Row By Agonizing Row»; SQL лучше всего работает с наборами данных, когда вам нужно что-то делать за строкой, это может быть признаком чего-то неправильного. –

0

Предлагаю добавить числовые первичные ключи к обеим таблицам и внешний ключ в country_code в таблице города. Одним из преимуществ будет более высокая производительность, поскольку первичные ключи индексируются.

Edit начинается здесь

Поскольку вопрос не просит вас предоставить фактические отношения, не думайте о том, чтобы вычислить его. В городе с самым высоким населением в стране будет самая высокая доля населения страны.

1

Для каждой страны, город, который имеет самое высокое отношение населения к этому население страны является городом с самым высоким населением, так что попробуйте это:

SELECT t.name, t.population, c.name, c.population 
FROM country c 
    JOIN city t 
     ON t.country_code = c.code 
     And population = 
       (Select Max(population) from city 
       Where country_code = c.Code) 

Но это еще может не улучшить производительность много .. если у вас нет указателей. Вам нужно указать индекс на country.code, а на city.country_code

Смежные вопросы