Найшвидший спосіб підрахувати точну кількість рядків у дуже великій таблиці?


234

Я натрапив на статті, які стверджують, що SELECT COUNT(*) FROM TABLE_NAMEбуде повільно, коли в таблиці багато рядків і багато стовпців.

У мене є таблиця, яка може містити навіть мільярди рядків [вона містить приблизно 15 стовпців]. Чи є кращий спосіб отримати точний підрахунок кількості рядків таблиці?

Перш ніж відповісти, врахуйте наступне:

  • Я шукаю незалежне рішення постачальника баз даних. Добре, якщо він охоплює MySQL , Oracle , MS SQL Server . Але якщо дійсно не існує незалежного рішення для постачальника баз даних, я прийму рішення про різні рішення для різних постачальників баз даних.

  • Я не можу використовувати жоден інший зовнішній інструмент для цього. Я в основному шукаю рішення на базі SQL.

  • Я не можу більше нормалізувати дизайн своєї бази даних. Він вже в 3NF, і ще багато коду вже написано навколо нього.


4
І просто цікаво, навіщо потрібна точна миттєва кількість рядків, коли їх у вас мільярди ...
zerkms

2
Чи не всі ми сподіваємось, що саме ця конструкція була оптимізована нашим постачальником даних?
KevinDTimm

5
@Swaranga, чи можете ви дізнатися трохи більше про те, яка мета цього обслуговування бази даних, яка повинна знати точну кількість рядків у таблиці? Я не можу собі уявити. І як каже Кевін, якби був швидший шлях, ніж COUNT (*), то постачальник СУБД (повинен) неодмінно повторно реалізувати COUNT (*), щоб використовувати його ...
Тоні Ендрюс

3
Безумовно, якщо таблиця записується часто, то ваш точний підрахунок буде точним лише для певного моменту часу, і навіть не може бути точним, якщо інші процеси записуються в таблицю, якщо ви не встановите запит блокування таблиці.
Стів Форд

2
Ви можете використовувати тригери вставки та видалення, щоб зберегти кількість показів?
папараццо

Відповіді:


246

Проста відповідь:

  • Незалежне рішення постачальника баз даних = використовувати стандарт = COUNT(*)
  • Є приблизні рішення SQL Server, але не використовуйте COUNT (*) = поза сферою

Примітки:

COUNT (1) = COUNT (*) = COUNT (PrimaryKey) на всякий випадок

Редагувати:

Приклад SQL Server (1,4 мільярда рядків, 12 стовпців)

SELECT COUNT(*) FROM MyBigtable WITH (NOLOCK)
-- NOLOCK here is for me only to let me test for this answer: no more, no less

1 пробіг, 5:46 хвилин, кількість = 1,401,659,700

--Note, sp_spaceused uses this DMV
SELECT
   Total_Rows= SUM(st.row_count)
FROM
   sys.dm_db_partition_stats st
WHERE
    object_name(object_id) = 'MyBigtable' AND (index_id < 2)

2 прогони, обидва за 1 секунду, підрахунок = 1,401,659,670

Другий має менше рядків = неправильно. Буде однаковою чи більшою, залежно від запису (видалення робиться тут не годинах)


9
Неа, COUNT(*) = COUNT(key). Це просто неправильно. Якщо NOT NULLобмежень немає - то вони можуть бути не рівними (як у результатах, так і в плані виконання).
zerkms

14
@zerkmsby: Для COUNT (ключ) я мав на увазі COUNT (основну клавішу), яка не повинна бути нульовою. Поясню
gnn

8
з (NOLOCK) - це не те, що дозволяє йому працювати на виробництві, і це може призвести до неточного підрахунку. Якщо ви використовуєте цей натяк, переконайтеся, що він запобігає блокуванню, але побічні ефекти на виробничій коробці полягають у тому, що ви можете рахувати рядки двічі в деяких ситуаціях або пропускати рядки в інших ситуаціях. NOLOCK краще використовувати на таблиці, до якої не пишуть, оскільки це дозволяє "брудно читати". Не радить людям користуватися цим натяком, якщо вони повністю не зрозуміють наслідки
Давос,

4
@mishrsud Єдиний точний запит - SELECT COUNT (*), але він повільний. Ви можете мати точну та повільну, грубу та швидку. Що ви робите, буде залежати від того, що важливіше для мети, для якої вам потрібно розраховувати. NO LOCK може з будь-якої причини включати або взагалі виключати рядки, які є серединою транзакції або рухомими сторінками.
Давос

5
@gbn дуже приємне рішення, ви можете сказати, для чого користь index_id < 2?
здійснити

29

Найшвидший спосіб на MySQL - це:

SHOW TABLE STATUS;

Ви негайно отримаєте всі свої таблиці з кількістю рядків (що є загальним) разом з великою кількістю додаткової інформації, якщо хочете.


1
Розумний спосіб .. за допомогою цього ви можете отримати кількість рядків декількох таблиць за 1 запит.
Deval Khandelwal

ви бігали на db, маючи таблиці з ~ мільярдами записів, як @gbn, і помітили час?
КНУ

яке значення є загальним числом рядків для всіх таблиць у базі даних? І це приблизні показники - що робити, якщо ви хочете точних значень кількості рядків?
Криверп

2
це взагалі не працює, наприклад, в INNODB, двигун зберігання даних читає кілька рядків та екстраполятів, щоб відгадати кількість рядків
Martijn Scheffer

10

Я натрапив на статті, які стверджують, що SELECT COUNT (*) ОТ TABLE_NAME буде повільним, коли в таблиці буде багато рядків і багато стовпців.

Це залежить від бази даних. Деякі прискорення підрахунку, наприклад, відстежуючи, чи є рядки живими чи мертвими в індексі, що дозволяє сканувати індекс лише для отримання кількості рядків. Інші цього не роблять, а отже, вимагають відвідувати весь стіл і рахувати живі рядки один за одним. Або буде повільно за величезним столом.

Зауважте, що, як правило, ви можете отримати добру оцінку, використовуючи інструменти оптимізації запитів, статистику таблиць тощо. Наприклад, у випадку PostgreSQL, ви можете проаналізувати результат explain count(*) from yourtableі отримати досить хорошу оцінку кількості рядків. Що підводить мене до вашого другого питання.

У мене є таблиця, яка може містити навіть мільярди рядків [вона містить приблизно 15 стовпців]. Чи є кращий спосіб отримати точний підрахунок кількості рядків таблиці?

Серйозно? :-) Ви справді маєте на увазі точний підрахунок з таблиці з мільярдами рядків? Ви справді впевнені? :-)

Якщо це дійсно , ви можете відслідковувати загальну кількість, використовуючи тригери, але пам’ятайте про одночасність та тупики, якщо це зробити.


Так, Денисе, потрібна точна кількість. :(
Swaranga Sarma

5
Це щаслива річ, що менеджери Google розумніші за вашого начальника ... Зображте, наскільки це буде повільно, якби він повернув точну кількість результатів пошуку для кожного з ваших запитів, а не дотримувався кошторисного числа.
Дені де Бернарді

Принаймні, ви співпереживаєте мені. Як щодо єдиного рішення Oracle? Це зменшить мою проблему до такої міри. Зараз клієнт використовує Oracle; тож якщо я придумаю вирішення лише для Oracle, це зробить [поки що]. :)
Swaranga Sarma

6
"Так, Денисе, потрібна точна кількість. :(" - ну я можу лише розмірковувати. Чи визначає процес обслуговування db, що в таблиці A є 42,123,876 рядків, а потім створює 42,123,876 порожніх рядків у таблиці B, а потім перебирає таблицю A та оновіть рядки в таблиці B ...? Або це божевільніше від цього? ;-)
Тоні Ендрюс

1
Трансакція 2 не може розпочатися до здійснення транзакції 1. Без оновлення "Таблиця підрахунків" багато операцій з оновленням можуть виконуватися паралельно. За допомогою "таблиці підрахунків" кожна транзакція повинна "отримати квиток" для оновлення рахунку. Тож транзакції починають чергуватися в касі (планувальник вирішує, хто наступним отримає замок на таблиці рахунків).
Ервін Смоут

10

Чи є кращий спосіб отримати точний підрахунок кількості рядків таблиці?

Щоб відповісти на ваше запитання просто, ні .

Якщо вам потрібен незалежний спосіб СУБД, це найшвидший спосіб:

SELECT COUNT(*) FROM TableName

Деякі постачальники СУБД можуть мати більш швидкі способи, які працюватимуть лише для їх систем. Деякі з цих варіантів уже розміщені в інших відповідях.

COUNT(*) повинні бути оптимізовані СУБД (принаймні будь-якою БД, гідною БД) у будь-якому випадку, тому не намагайтеся обійти їх оптимізації.

Зі сторони:
я впевнений, що для багатьох інших ваших запитів також потрібно тривати довгий час, оскільки розмір вашої таблиці. Будь-які проблеми щодо ефективності, ймовірно, повинні бути вирішені, продумуючи дизайн вашої схеми з урахуванням швидкості. Я розумію, ви сказали, що це не варіант змінити, але може виявитись, що запити 10+ хвилин - це теж не варіант. 3-й НФ - це не завжди найкращий підхід, коли вам потрібна швидкість, і іноді дані можуть бути розділені на кілька таблиць, якщо записи не потрібно зберігати разом. Щось подумати ...


10

Цей сценарій я отримав з іншого питання / відповіді StackOverflow:

SELECT SUM(p.rows) FROM sys.partitions AS p
  INNER JOIN sys.tables AS t
  ON p.[object_id] = t.[object_id]
  INNER JOIN sys.schemas AS s
  ON s.[schema_id] = t.[schema_id]
  WHERE t.name = N'YourTableNameHere'
  AND s.name = N'dbo'
  AND p.index_id IN (0,1);

Моя таблиця має 500 мільйонів записів, і вищезазначені показники отримують менше ніж 1 мс. Тим часом,

SELECT COUNT(id) FROM MyTable

займає цілих 39 хвилин, 52 секунди!

Вони дають точно таку ж кількість рядків (у моєму випадку - рівно 519326012).

Я не знаю, чи завжди так було б.


Чи можете ви додати параметр для підрахунку рядків за допомогою цього запиту? Приклад: Виберіть COUNT (1) ВІД ТАБЛЕНАМУ, де ColumnFiled = '1' З вашим запитом?
VnDevil

Тобто підрахунок - кількість рядків (записів) є "підрахунком" у цьому випадку. "500 мільйонів записів" було приблизним числом, а "519326012" - точною кількістю рядків, або числом. Рядки = записи = кількість.
JakeJ

9

Ви можете спробувати цей sp_spaceused (Transact-SQL)

Відображає кількість рядків, зарезервований простір на диску та простір на диску, що використовується таблицею, індексованим видом або чергою Service Broker у поточній базі даних, або відображається простір на диску, зарезервований та використаний цілою базою даних.


Не вдасться sp_spaceused приблизно рахувати?
Swaranga Sarma

1
FYI: Для цього використовується sys.dm_db_partition_stats внутрішньо
gbn

6

Якщо видання SQL Server 2005/2008, ви можете використовувати DMV для обчислення кількості рядків у таблиці:

-- Shows all user tables and row counts for the current database 
-- Remove is_ms_shipped = 0 check to include system objects 
-- i.index_id < 2 indicates clustered index (1) or hash table (0) 
SELECT o.name, 
 ddps.row_count 
FROM sys.indexes AS i 
 INNER JOIN sys.objects AS o ON i.OBJECT_ID = o.OBJECT_ID 
 INNER JOIN sys.dm_db_partition_stats AS ddps ON i.OBJECT_ID = ddps.OBJECT_ID 
 AND i.index_id = ddps.index_id 
WHERE i.index_id < 2 
 AND o.is_ms_shipped = 0 
ORDER BY o.NAME 

Для двигуна бази даних SQL Server 2000 працюватимуть sysindexes, але настійно рекомендується уникати використання його у майбутніх випусках SQL Server, оскільки він може бути видалений найближчим часом.

Зразок коду, взятого з: Як швидко та безболісно отримати підрахунки рядків таблиці


Це орієнтовно не точно : дивіться мою відповідь будь ласка
gbn

Чи знаєте ви приклад, коли це не точно? AFAIK, це не залежить від оновленої статистики.
Аліреза Мадда

5

я використовую

select /*+ parallel(a) */  count(1) from table_name a;

виберіть / * + паралельно (a) * / count (1) від table_name a
Mainsh S

5

Я ніде не є таким експертом, як інші, хто відповів, але у мене виникли проблеми з процедурою, яку я використовував для вибору випадкового рядка з таблиці (не надто актуально), але мені потрібно було знати кількість рядків у моїй довідковій таблиці обчислити випадковий індекс. Використовуючи традиційну роботу Count (*) або Count (1), але я час від часу отримував до 2 секунд для запуску запиту. Тож замість цього (для моєї таблиці під назвою 'tbl_HighOrder') я використовую:

Declare @max int

Select @max = Row_Count
From sys.dm_db_partition_stats
Where Object_Name(Object_Id) = 'tbl_HighOrder'

Це чудово працює, і час запитів у студії менеджменту дорівнює нулю.


1
FWIW, ви повинні згадати Якого постачальника баз даних ви використовуєте; Я думаю, що твердження буде дещо іншим, залежно від постачальника.
ToolmakerSteve

5

Ну, пізно на 5 років і не впевнений, чи допоможе це:

Я намагався порахувати ні. рядків у таблиці SQL Server за допомогою MS Studio SQL Server Management Studio і зіткнувся з деякою помилкою переповнення, тоді я використав нижче:

виберіть count_big (1) ВІД [dbname]. [dbo]. [FactSampleValue];

Результат :

24296650578 рядків


5

Я знайшов цю хорошу статтю SQL Server – HOW-TO: швидко знайдіть точну кількість рядків для таблиці, з martijnh1якої дає хороший підсумок для кожного сценарію.

Мені потрібно це розширити там, де мені потрібно вказати підрахунок, виходячи з конкретної умови, і коли я зрозумію цю частину, я оновлю цю відповідь далі.

А поки ось деталі статті:

Спосіб 1:

Запит:

SELECT COUNT(*) FROM Transactions 

Коментарі:

Виконує повне сканування таблиці. Повільно на великих столах.

Спосіб 2:

Запит:

SELECT CONVERT(bigint, rows) 
FROM sysindexes 
WHERE id = OBJECT_ID('Transactions') 
AND indid < 2 

Коментарі:

Швидкий спосіб отримати кількість рядків Залежить від статистики і є неточним.

Запустіть оновлення DBCC (база даних) із COUNT_ROWS, що може зайняти значний час для великих таблиць.

Спосіб 3:

Запит:

SELECT CAST(p.rows AS float) 
FROM sys.tables AS tbl 
INNER JOIN sys.indexes AS idx ON idx.object_id = tbl.object_id and
idx.index_id < 2 
INNER JOIN sys.partitions AS p ON p.object_id=CAST(tbl.object_id AS int) 
AND p.index_id=idx.index_id 
WHERE ((tbl.name=N'Transactions' 
AND SCHEMA_NAME(tbl.schema_id)='dbo')) 

Коментарі:

Те, як студія управління SQL рахує рядки (подивіться властивості таблиці, зберігання, кількість рядків). Дуже швидко, але все-таки приблизна кількість рядків.

Спосіб 4:

Запит:

SELECT SUM (row_count) 
FROM sys.dm_db_partition_stats 
WHERE object_id=OBJECT_ID('Transactions')    
AND (index_id=0 or index_id=1); 

Коментарі:

Швидка (хоча і не така швидка, як метод 2) роботи, і однаково важлива, надійна.


Дякую! Дійсно корисна порада. У мене немає дозволу на перегляд системних таблиць, тому метод 4 - це не я. Однак метод 3 досить хороший.
Ніколас Хамфрі

3

Я не думаю, що існує загальне завжди швидке рішення: деякі RDBMS / версії мають специфічну оптимізацію для SELECT COUNT(*)використання швидших варіантів, а інші просто сканування таблиці. Вам потрібно буде зайти на сайти документації / підтримки для другого набору, де, ймовірно, знадобиться записати більш конкретний запит, як правило, той, який певним чином потрапляє в індекс.

Редагувати:

Ось думка, яка може спрацювати, залежно від вашої схеми та розподілу даних: чи є у вас індексований стовпець, який посилається на зростаюче значення, числовий ідентифікатор, що збільшується, скажімо, або навіть часову позначку або дату? Тоді, припускаючи, що видалення не відбувається, слід мати можливість зберігати кількість до деякого недавнього значення (дата вчорашнього дня, найвище значення ідентифікатора в деякій недавній вибірковій точці) та додавати кількість за межі цього, що має дуже швидко вирішитись в індексі . Звичайно, дуже залежать від значень та індексів, але застосовні майже до будь-якої версії будь-якої СУБД.


Я дуже сподіваюся, що будь-яка гідна СУБД буде використовувати індекс для SELECT COUNT(*). Навіть MySQL, мабуть, робить це.
sleske

припускаючи, що делетів не трапляється - серйозно ?? ; p
ToolmakerSteve

3

Я запізнююсь на це питання, але ось що ви можете зробити з MySQL (коли я використовую MySQL). Я ділюся своїми спостереженнями тут:

1) SELECT COUNT(*) AS TOTAL_ROWS FROM <TABLE_NAME>

Результат
Кількість рядків: 508534
Консольний вихід : Порушені рядки: 0 Знайдені рядки: 1 Попередження: 0 Тривалість 1 запиту: 0,125 сек.
Знадобиться час для таблиці з великою кількістю рядків, але кількість рядків дуже точна.

2) SHOW TABLE STATUS or SHOW TABLE STATUS WHERE NAME="<TABLE_NAME>"

Результат
Кількість рядків: 511235 Вихід
консолі : Порушені рядки: 0 Знайдені рядки: 1 Попередження: 0 Тривалість 1 запиту: 0,250 сек Підсумок: Кількість рядків не точна.

3) SELECT * FROM information_schema.tables WHERE table_schema = DATABASE();

Результат
Кількість рядків: 507806
Консольний вихід : Порушені рядки: 0 Знайдені рядки: 48 Попередження: 0 Тривалість 1 запиту: 1.701 сек.
Кількість рядків не точна.

Я не є експертом по MySQL або базі даних, але я виявив, що для дуже великих таблиць ви можете скористатися варіантом 2 або 3 і отримати "справедливе уявлення" про кількість рядків.

Мені потрібно було отримати ці підрахунки рядків для відображення деяких статистичних даних в інтерфейсі користувача. З вищенаведених запитів я знав, що загальна кількість рядків перевищує 500 000, тому я придумав показ статистики типу "Більше 500 000 рядків", не показуючи точну кількість рядків.

Можливо, я не дуже відповідав на питання ОП, але я ділюсь тим, що робив у ситуації, коли потрібна така статистика. У моєму випадку показ приблизних рядків був прийнятним, і для мене вищезгадане спрацювало.


2

Не зовсім DBMS-агностичне рішення, але принаймні ваш код клієнта не побачить різниці ...

Створіть іншу таблицю T, що містить лише один рядок і одне ціле поле N 1 , і створіть INSERT TRIGGER, який щойно виконує:

UPDATE T SET N = N + 1

Також створіть DELETE TRIGGER, який виконує:

UPDATE T SET N = N - 1

СУБД, яка вартує її солі, гарантуватиме атомність операцій вище 2 , а N міститиме точний підрахунок рядків у всі часи, що потім дуже швидко отримати просто:

SELECT N FROM T

Хоча тригери залежать від СУБД, вибір з T не є, і клієнтський код не потрібно буде змінювати для кожної підтримуваної СУБД.

Однак це може мати певні проблеми зі масштабуванням, якщо таблиця є INSERT або DELETE, особливо якщо ви не вступаєте в команду відразу після INSERT / DELETE.


1 Ці назви є просто заповнювачами - використовуйте щось більш значиме у виробництві.

2 Тобто N не може бути змінено одночасно транзакцією між читанням і записом на N, доки і читання, і запис виконуються в одному операторі SQL.


2

Буквально божевільна відповідь, але якщо у вас створена якась система реплікації (для системи з мільярдом рядків, я сподіваюсь, що ви це зробите), ви можете використовувати приблизний оцінювач (як MAX(pk)), поділити це значення на кількість невільників у вас є, запустіть кілька запитів паралельно.

Здебільшого ви розділите запити між рабами на основі найкращого ключа (або, мабуть, первинного ключа) таким чином (ми будемо використовувати 250000000 як наші рядки / раби):

-- First slave
SELECT COUNT(pk) FROM t WHERE pk < 250000000
-- Ith slave where 2 <= I <= N - 1
SELECT COUNT(pk) FROM t WHERE pk >= I*250000000 and pk < (I+1)*250000000
-- Last slave
SELECT COUNT(pk) FROM t WHERE pk > (N-1)*250000000

Але вам потрібен лише SQL. Який бюст. Гаразд, скажімо, ви садомазохіст. Для головного (або найближчого раба) вам, швидше за все, потрібно буде створити для цього таблицю:

CREATE TABLE counter_table (minpk integer, maxpk integer, cnt integer, slaveid integer)

Тож замість того, щоб лише вибрані вами працювали у ваших рабах, вам доведеться зробити вставку, схожу на це:

INSERT INTO counter_table VALUES (I*25000000, (I+1)*250000000, (SELECT COUNT(pk) FROM ... ), @@SLAVE_ID)

Ви можете зіткнутися з проблемами, коли раби записують до таблиці на майстра. Можливо, вам доведеться отримати ще більше садистів - я маю на увазі креатив:

-- A table per slave!
INSERT INTO counter_table_slave_I VALUES (...)

Зрештою, у вас повинен бути підлеглий, який існує останнім у шляху, пройденому графіком реплікації, щодо першого підлеглого. Цей раб тепер повинен мати всі інші зустрічні значення, і він повинен мати свої власні значення. Але до того часу, коли ви закінчите, напевно додаються рядки, тому вам доведеться вставити ще один компенсуючи записаний макс pk у ваш counter_table та поточний max pk.

У цей момент вам доведеться виконати сукупну функцію, щоб визначити, яка загальна кількість рядків, але це простіше, оскільки ви будете виконувати її на максимум "кількість невільників, які ви маєте та змінюєте".

Якщо у вас є ситуація, коли у рабів є окремі таблиці, ви можете UNIONотримати всі потрібні рядки.

SELECT SUM(cnt) FROM (
    SELECT * FROM counter_table_slave_1
      UNION
    SELECT * FROM counter_table_slave_2
      UNION
    ...
  )

Або ви знаєте, будьте трохи менш божевільними і перенесіть свої дані в розподілену систему обробки, або, можливо, використовуйте рішення для зберігання даних (що дасть вам і в майбутньому приголомшливе скорочення даних).

Зверніть увагу, це залежить від того, наскільки налаштована ваша реплікація. Оскільки основне вузьке вузьке місце, швидше за все, буде постійним сховищем, якщо у вас є жорстке сховище або погано відокремлені сховища даних із сильним шумом сусідів, це, ймовірно, запустить вас повільніше, ніж просто чекати єдиногоSELECT COUNT(*) ...

Але якщо у вас хороша реплікація, то ваші підвищення швидкості повинні бути безпосередньо пов'язані з кількістю або рабами. Насправді, якщо для самостійного виконання запиту підрахунку потрібно 10 хвилин, а у вас є 8 рабів, ви скоротили б час менше ніж на пару хвилин. Можливо, годину, щоб випрасувати деталі цього рішення.

Звичайно, ви ніколи не отримаєте напрочуд точну відповідь, оскільки це розподілене рішення вводить трохи часу, коли рядки можна видалити та вставити, але ви можете спробувати отримати розподілений замок рядків у тому ж екземплярі та отримати точний підрахунок рядків у таблиці за певний момент часу.

Насправді, це здається неможливим, оскільки ви в основному застрягли з рішенням, призначеним лише для SQL, і я не думаю, що ви забезпечили механізм миттєвого запуску стриманого і заблокованого запиту по декількох рабах. Можливо, якби ви мали контроль над файлом журналу реплікації ... а це означає, що ви буквально для цього спрямовували б раби, що, без сумніву, повільніше, ніж просто запускати запит підрахунку на одній машині.

Отже, є мої дві копійки 2013 року.


2

Якщо тригер вставки занадто дорогий у використанні, але триггер видалення може бути наданий, і є автоматичне збільшенняid , після того, як підрахувати всю таблицю один раз і запам'ятати рахунок як last-countі last-counted-id,

то кожен день просто потрібно порахувати за id> last-counted-id, додати до цього last-countі зберегти нове last-counted-id.

Тригер видалення буде декрементом останнього підрахунку, якщо id видаленої записи <= last-counted-id.


.. Вибачте, не встигли показати SQL, який би використовувався (мій SQL іржавий). Якщо хтось хоче відредагувати мою відповідь, щоб додати SQL, це було б чудово!
ToolmakerSteve

1

Якщо у вас є типова структура таблиці зі стовпцем первинного ключа з автоматичним збільшенням, у якому рядки ніколи не видаляються, наступним буде найшвидший спосіб визначити кількість записів і має працювати аналогічно для більшості баз даних ANSI:

SELECT TOP(1) <primarykeyfield> FROM <table> ORDER BY <primarykeyfield> DESC;

Я працюю з таблицями MS SQL, що містять мільярди рядків, для яких потрібні часи відгуку, що знаходяться в другій секунді, включаючи кількість записів. Аналогічний SELECT COUNT (*) обробляє порівняння.


1
Не зовсім правда - що робити, якщо INSERTтранзакцію відкрутити назад? Це значення первинного ключа буде відсутнім, тому фактична кількість записів була б на одну меншу, ніж максимальна величина.
Сер Кріспалот

Можуть бути прогалини в послідовності. Зазвичай результат відкатів.
Osa E

Насправді, існує відповідна модифікація цієї відповіді, яка може бути значно швидшою, ніж count(*)якщо постачальник баз даних не має достатньої оптимізації count(*): щодня слідкуйте за останнім автоіндексом та відповідним його підрахунком, а потім запитайте про кількість записів минулих. Також можна обробити deletes, якщо додати тригер при видаленні, який зменшує попередній загальний результат, якщо видалений ідентифікатор запису <= той останній автоматичний індекс.
ToolmakerSteve

1

Для сервера Sql спробуйте це

SELECT T.name, 
       I.rows AS [ROWCOUNT] 
FROM   sys.tables AS T 
       INNER JOIN sys.sysindexes AS I 
               ON T.object_id = I.id AND I.indid < 2 
WHERE T.name = 'Your_Table_Name'
ORDER  BY I.rows DESC 


0

Поставте індекс у якийсь стовпець. Це повинно дозволити оптимізатору виконати повне сканування блоків індексів замість повного сканування таблиці. Це скоротить ваші витрати на введення-вивільнення вниз. Подивіться план виконання до і після. Потім вимірюйте час настінного годинника обома способами.


Якщо таблиця має мільярди рядків без індексу в будь-якому стовпці, то будуть широкі питання щодо продуктивності, набагато вищі за потреби, виражені в оригінальному питанні .., але добре, що ви це згадуєте (не припускайте нічого!) :)
ToolmakerSteve

0

Якщо ви використовуєте Oracle, як щодо цього (якщо припустити оновлення статистики таблиці):

select <TABLE_NAME>, num_rows, last_analyzed from user_tables

last_analyzed покаже час, коли статистика востаннє збиралася.



-1

На SQL сервері 2016 я можу просто перевірити властивості таблиці, а потім вибрати вкладку "Зберігання" - це дає мені кількість рядків, дисковий простір, який використовується таблицею, використаний простір індексу тощо.


Він шукав database vendor independent solution. Також для цього потрібен графічний інтерфейс, і його неможливо автоматизувати. Також це не швидше, ніж COUNT (*)
Фрідер

-3

Можливо, трохи пізно, але це може допомогти іншим для MSSQL

; З RecordCount AS (SELECT ROW_NUMBER () OVER (ORDER by COLUMN_NAME) AS [RowNumber] OF TABLE_NAME) SELECT MAX (RowNumber) З RecordCount


Це суттєво НЕ БЕШЕ, ніж COUNT (), якщо нам НЕ ДУЖЕ пощастило і оптимізатору вдається оптимізувати його до COUNT () - навіщо запитувати його на SORT у випадковому стовпчику?!?
dsz
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.