MySQL « Выполнение select count на больших таблицах

Вот такой запрос

/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .mysql.geshi_code {font-family:monospace;} .mysql.geshi_code .imp {font-weight: bold; color: red;} .mysql.geshi_code .kw1 {color: #990099; font-weight: bold;} .mysql.geshi_code .kw2 {color: #990099; font-weight: bold;} .mysql.geshi_code .kw3 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw4 {color: #999900; font-weight: bold;} .mysql.geshi_code .kw5 {color: #999900; font-weight: bold;} .mysql.geshi_code .kw6 {color: #FF9900; font-weight: bold;} .mysql.geshi_code .kw7 {color: #FF9900; font-weight: bold;} .mysql.geshi_code .kw8 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw9 {color: #9900FF; font-weight: bold;} .mysql.geshi_code .kw10 {color: #CC0099; font-weight: bold;} .mysql.geshi_code .kw11 {color: #CC0099; font-weight: bold;} .mysql.geshi_code .kw12 {color: #009900;} .mysql.geshi_code .kw13 {color: #000099;} .mysql.geshi_code .kw14 {color: #000099;} .mysql.geshi_code .kw15 {color: #000099;} .mysql.geshi_code .kw16 {color: #000099;} .mysql.geshi_code .kw17 {color: #000099;} .mysql.geshi_code .kw18 {color: #000099;} .mysql.geshi_code .kw19 {color: #000099;} .mysql.geshi_code .kw20 {color: #000099;} .mysql.geshi_code .kw21 {color: #000099;} .mysql.geshi_code .kw22 {color: #000099;} .mysql.geshi_code .kw23 {color: #000099;} .mysql.geshi_code .kw24 {color: #000099;} .mysql.geshi_code .kw25 {color: #000099;} .mysql.geshi_code .kw26 {color: #000099;} .mysql.geshi_code .kw27 {color: #00CC00;} .mysql.geshi_code .coMULTI {color: #808000; font-style: italic;} .mysql.geshi_code .co1 {color: #808080; font-style: italic;} .mysql.geshi_code .co2 {color: #808080; font-style: italic;} .mysql.geshi_code .es0 {color: #004000; font-weight: bold;} .mysql.geshi_code .es1 {color: #008080; font-weight: bold;} .mysql.geshi_code .br0 {color: #FF00FF;} .mysql.geshi_code .sy1 {color: #CC0099;} .mysql.geshi_code .sy2 {color: #000033;} .mysql.geshi_code .st0 {color: #008000;} .mysql.geshi_code .nu0 {color: #008080;} .mysql.geshi_code span.xtra { display:block; }
SELECT COUNT(*) FROM large_table where id > 10 AND id < 10000000


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

UPD:

Медленно это 0.5-1с на таблице с количеством строк > 1 600 000.

1 ответов


Нужно разбираться в каждом конкретном случае, так как универсального рецепта нет. Есть ряд методов, но, повторюсь, чтобы понять какой конкретно выбрать, нужно знать и задачу, и инфраструктуру. Методы:
1. Денормализировать данные. Хранить количество как значение поля и изменять при соответствующих действиях. Пример: количество сообщений пользователя форума хранить как поле в таблице "Users", а не пытаться делать "SELECT count(*) FROM Messages WHERE id_User = my_id_user".
2. Если id автоинкриментно и записи не удаляются, то count(*) = top_value - bottom_value
3. Если на таблице много модифицирующих запросов (INSERT, UPDATE, DELETE), то использовать slave базу данных для чтения (модифицирующие запросы идут на master, все селекты делаем на slave).
4. Можно попробовать запрос на ограничение данных сделать через JOIN -результат ограничивающего запроса будет храниться в кэше mysql (при отсутствии модифицирующих запросов) и повторный подсчет количества будет на порядок быстрее

SELECT count(*)
FROM Table t
  JOIN (SELECT id FROM Table WHERE id beween 10 and 10000) t2 ON t.id = t2.id
5. Поменять бизнес-модель и обойтись без подсчета вообще :)

Подбирайте под задачу и конкретные условия.

Добавте индекс на это поле


Возможно, BETWEEN будет работать быстрее?

WHERE id BETWEEN 10 AND 9999999