2011-06-21 37 views
7

Aşağıdaki gibi bir sorgum var;Yavaş SQL performansı

SELECT COUNT(Id) FROM Table 

Tablo 33 milyon kayıt içeren - bu Id ve başka bir endekse birincil anahtar içerir.

Sorgu 30 saniye sürüyor.

fiili yürütme planı bir kümelenmiş dizin tarama kullanır gösterir.

Biz tablo incelendiğinde ve bu linkte gösterilen ilk sorgusunu kullanarak parçalanmış değil bulduk: http://sqlserverpedia.com/wiki/Index_Maintenance.

bu sorgu çok yavaş neden ve nasıl düzeltebilirim olarak herhangi bir fikir.

Tablo Tanımı: Ben fark etmiş

CREATE TABLE [dbo].[DbConversation](
[ConversationID] [int] IDENTITY(1,1) NOT NULL, 
[ConversationGroupID] [int] NOT NULL, 
[InsideIP] [uniqueidentifier] NOT NULL, 
[OutsideIP] [uniqueidentifier] NOT NULL, 
[ServerPort] [int] NOT NULL, 
[BytesOutbound] [bigint] NOT NULL, 
[BytesInbound] [bigint] NOT NULL, 
[ServerOutside] [bit] NOT NULL, 
[LastFlowTime] [datetime] NOT NULL, 
[LastClientPort] [int] NOT NULL, 
[Protocol] [tinyint] NOT NULL, 
[TypeOfService] [tinyint] NOT NULL, 
    CONSTRAINT [PK_Conversation_1] PRIMARY KEY CLUSTERED 
(
[ConversationID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 
GO 

bir şey veritabanı 1Mb parçalar büyümeye ayarlanmış olmasıdır.

O canlı bir sistem bu yüzden biz oynayabilir ne kısıtlanmış - herhangi fikirler?

GÜNCELLEME:

Tamam - biz artık kritik bir sorun değil çok uygun sütunlarda yeni kümelenmemiş indeksleri ekleyerek gerçek faiz sorguda performansı geliştirdik.

SELECT COUNT olsa yine de yavaş - nolock ipuçları ile çalıştı - hiçbir fark.

Hepimiz AutoGrowth'un daha büyük bir sayı yerine 1Mb'ye ayarlanmış bir şey olduğunu düşünüyoruz, ancak bunun bu etkiyi şaşırttığını düşünüyoruz. Diskteki MDF fragmantasyonu olası bir neden olabilir mi?

+1

Soru 1: Gerçekten tam sayıya ihtiyacın var mı? Ya da sadece bir tahmin? –

+0

Ne de - bu sadece başka bir şey üzerinde yavaş performans gözlemledikten sonra koştuğumuz bir sorudur. Çok yavaş olduğunu bulmak için oldukça şaşırdık. İstatistikleri güncellemeyi deneyeceğim, ancak otomatik güncellemeye ayarlanmışlar. – BonyT

+0

Sadece sabit kullanamaz mısın? Yani, 33 milyona sahip olan ya da aslında 33.212.293 kayıtlarının arasındaki fark sizi nasıl etkiliyor? – bevacqua

cevap

5

Sıklıkla okunan/eklenen/güncelleştirilmiş bir tablo mu? Seçiminizle eşzamanlı olarak güncelleme/ekleme etkinliği var mı?

Benim tahminim gecikme çakışması yüzünden olmasıdır.

Dev sunucumda 179 satırda 189 milyon satırlık bir sayı çalıştırabilirim, ancak bu tabloya başka bir şey yazmıyor.

sen yapabileceğiniz çekişme veya mutlak doğruluğu hakkında çok endişeli değilseniz: meta verilere dayalı bir sayım verecektir

exec sp_spaceused 'MyTableName'.

size daha kesin sayısı istiyorum ama bir NOLOCK ipucu ile mevcut sorgu yapabilirsiniz eşzamanlı DELETE veya INSERT etkinliği yansıtır eğer ille umursamıyorsan:

SELECT COUNT(id) FROM MyTable WITH (NOLOCK) için satır düzeyinde kilitleri almazsınız sorgunuz ve daha hızlı çalışmalı. fıkra sizin ihtiyacına göre nerede 0-5 saniye

kullanım içindeki tüm masaları sayımı getirebilir bu sorguları kullanarak

+0

Çok yoğun bir veritabanı değil - çekişme bir sorun değil (ifade neredeyse her zaman 30 saniyeye karşılık vermek için aynı zaman alır ve NOLOCK ipucu kullanmak fark etmez.) – BonyT

+0

@BonyT - O zaman başka sorunlarınız var. Bu masa ne kadar geniştir? Bu doğrudan "COUNT" ile alakalı değil, ancak sayıları almak için SQL'in kaç sayfayı çekmesi gerektiğini etkiliyor, bu da daha yüksek hacimlerde önemli olabilir. Başka hangi mükemmel sorunları yaşıyorsunuz? – JNK

+0

Kabul edildi, asıl sorunun ne olduğunu asla bilmeyebilir/birisi elses çiminde olduğu gibi burada ve anladığım bir geçici çözümü anladım. – BonyT

1
use [DatabaseName] 

select tbl.name, dd.rows from sysindexes dd 
inner join sysobjects tbl on dd.id = tbl.id where dd.indid < 2 and tbl.xtype = 'U' 

select sum(dd.rows)from sysindexes dd 
inner join sysobjects tbl on dd.id = tbl.id where dd.indid < 2 and tbl.xtype = 'U' 

.....

+0

Başvuru sitesi: http://planetofcoders.blogspot.com/2011/06/how-to-count-all-rows-in-particular.html –

+1

Yayını dikkatli bir şekilde okuyun, endişesi 'select count (kimlik sayısı) değil) '' – Rahul

2

Düşünceler: (ANSI SQL göre) "kaç satır" için doğrudur

  • kullanın SELECT COUNT(*). Kimlik PK ise ve bu nedenle null olmamasına rağmen, SQL Server ID olarak sayılır. Satırlar değil.

  • Yaklaşık sayımlarla yaşayabiliyorsanız, sys.dm_db_partition_stats dosyasını kullanın. Burada Cevabımı bakınız: dosyaları 1MB parçalarıyla büyür, bu dosya sisteminde parçalanmış olabilir:

  • sen kirli yaşayabilirsen Fastest way to count exact number of rows in a very large table?WITH (NOLOCK)

+0

sorgusunun oldukça yavaş bir performansı Optimize edici, parantez içine ne koyarsanız yapın, aynı planı etkin olarak kullanması gerçekten önemli değil. Bazı insanlar olsa "*" kullanarak telaşlı. Bu konuyla ilgisi ne olursa olsun. – BonyT

+0

@BonyT: "Telaşlı" olduğunu düşünüyorsanız, [farklar] 'ın farkında olduğunu * doğrulamanızı öneririm (http://stackoverflow.com/questions/1221559/count-vs-count1/1221649#1221649) (col) sayımla aynı planı vermeyebilir (*). Bu yüzden benim önerim – gbn

+0

Evet biz - aslında başladık * :) – BonyT

0

Başka fikri kullanmak okur. Bunu SQL tarafından göremezsiniz, bir disk birleştirme aracı kullanarak görüyorsunuz.

İlgili konular